Задать вопрос
@Bersonazh

Может кто помочь отловить ошибку в работе анимации?

Добрый день! Новичок в канвас. На основе огромной кучи примеров пытаюсь слепить картинки по пикселям с помощью "падающих звезд" в координаты точек. Собственно, проблема, на текущий момент, в вызове requestAnimationFrame. Один я вызываю на аниамцию падения звезды, и так полагаю, что необходимо вызвать и второй, чтобы этих звезд было столько же, сколько и пикселей. Прошу знающих помочь разобраться в чем ошибка, сижу на одном месте уже не первый день.

Демо

Горе функция:
animate: function () {

            if (this.dataToDraw && this.dataToDraw[this.iterator]) {
                let xStart = this.dataToDraw[this.iterator].xStart
                let xFinish = this.dataToDraw[this.iterator].xFinish
                let yStart = this.dataToDraw[this.iterator].yStart
                let yFinish = this.dataToDraw[this.iterator].yFinish


                const drawStroke = () => {

                    xStart = xStart + (xFinish - xStart) * (this.iterator / 2)
                    yStart = yStart + (yFinish - yStart) * (this.iterator / 2)

                    let x2 = xStart + (xFinish - xStart) * ((this.iterator / 2) + 250)
                    let y2 = yStart + (yFinish - yStart) * ((this.iterator / 2) + 250)

                    const rab = Math.sqrt(Math.pow((x2 - xStart), 2) + Math.pow((y2 - yStart), 2))

                    const gradient = ctx.createLinearGradient(xStart, yStart, x2, y2)
                    gradient.addColorStop(1, this.dataToDraw[this.iterator].rgbaStart)
                    gradient.addColorStop(0, this.dataToDraw[this.iterator].rgbaStop)

                    ctx.strokeStyle = gradient

                    if (rab < 1) return
                    else {

                        ctx.clearRect(0, 0, width, height)
                        ctx.beginPath()
                        // ctx.strokeText('.', xFinish, yFinish)
                        ctx.moveTo(xStart, yStart);
                        ctx.lineTo(x2, y2);
                        ctx.closePath()
                        ctx.stroke();
                    }

                    requestAnimationFrame(drawStroke)

                }

                drawStroke()
            }

            this.iterator++

            requestAnimationFrame(this.animate)

        }


Весь фрагмент:
spoiler

const canvas = document.querySelector('canvas')
    const ctx = canvas.getContext('2d')

    const height = window.innerHeight
    const width = window.innerWidth

    function Builder() {
        this.dataToDraw = []
        this.radius = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height) / 2
        this.iterator = 0
        this.init()
    }


    Builder.prototype = {
        init: function () {
            this.imageObj = new Image();
            this.imageObj.src = ' data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAkCAYAAAAHKVPcAAACd0lEQVRYhe2Xv2+jMBzF+/8ztRtbthxLMyBQGeqhXBQhobtESQcYggQZQpUqREIIwfBuSOGMsY2h6Kaz5CU/7I+f3/fZfsA3m6UZbZ/aHtgPwvUB7+S38gBb24OlGXh//TUPxCVO21Wdw5PSAEWWg+jmZIAeRF1WILoJSzNwS69KAzRKFFk+D0TTiiyHv3IH/1xkeatcso/mhQCAZB9hZ3uoy6o3ceQH2Nleq5qlGdja3vwQAPC2eAHRTVziFHVZYfclPa87T89IDtH8EMk+6kwiAqA70U1lPylB1GWlNDFPlTEgUggAnX0f092FMw8EvR1TumrFSCHchdMb+OgHKLIcdVkh2UdwHsVeUVVDCMHzAy9FiyyXgqh4QwhBR3jjehqQzo+tpHRV4l8aVvRgmyX5u/Kvcr3EKYD7oSeCCNeH+SCcp2cAXYUa4/krVwjhr372UlcZgt0OelVHP8DRD4S/4+WGTJFRxrQ0Azvbw2f8gc/4A+H6oJykTbXwVJGW6GZJvpUTqmkqhVCRWtSJbqLIcq5piW52FBmMbZnpVFd8S694W7z0DKsMMfXsYEHqsuqBNCUuhbilV4beRbg+9LyytT2cwxMucdpLTxnI5gcZhmD3syFnFaIPKvqeSlcFvTAadBCCXjF7o6a9wl7t2IlY0Ob75pkghaAzgJ2IVol35WcrS3aiSiHoQdjEYyfhHVTsdoqeBcoQvElY07KN9YcouicrAaBXcryVnsPTvUoexfdOuScoc/Hemkc/GAQF7kaUvdCkEHQF8MxXl1UHdOqbdNTZwTsBWfONfXMMQgB3yTdLIrym1WXV5onK+3USxL9o/yGa9gf+5N60Efba5wAAAABJRU5ErkJggg=='
            const imageWidth = this.imageObj.width;
            const imageHeight = this.imageObj.height;

            if (imageWidth > 0) this.drawImage(imageWidth, imageHeight)
            else setTimeout(() => this.init())

        },
        drawImage: function (imageWidth, imageHeight) {

            canvas.height = window.innerHeight
            canvas.width = window.innerWidth

            this.imageXOffset = canvas.width / 2 - this.imageObj.width / 2
            this.imageYOffset = canvas.height / 2 - this.imageObj.height / 2


            ctx.drawImage(this.imageObj, this.imageXOffset, this.imageYOffset);

            const imageData = ctx.getImageData(this.imageXOffset, this.imageYOffset, imageWidth, imageHeight);
            const data = imageData.data;

            ctx.clearRect(0, 0, canvas.width, canvas.height)

            for (let yFinish = 0; yFinish < imageHeight; yFinish++) {
                for (let xFinish = 0; xFinish < imageWidth; xFinish++) {
                    let r = data[((imageWidth * yFinish) + xFinish) * 4];
                    let g = data[((imageWidth * yFinish) + xFinish) * 4 + 1];
                    let b = data[((imageWidth * yFinish) + xFinish) * 4 + 2];

                    if (r !== 0) {
                        let angle = Math.ceil(Math.random() * 360) * (Math.PI / 180)
                        let xStart = Math.sin(angle * this.radius) * canvas.width * 5
                        let yStart = Math.cos(angle * this.radius) * canvas.height * 5
                        this.dataToDraw.push({
                            xStart,
                            yStart,
                            rgbaStart: 'rgba(' + r + ',' + g + ',' + b + ', 1)',
                            xFinish: xFinish + this.imageXOffset,
                            yFinish: yFinish + this.imageYOffset,
                            rgbaStop: 'rgba(' + r + ',' + g + ',' + b + ', 0)',
                        })
                    }
                }
            }
            this.animate()
        },
        animate: function () {

            if (this.dataToDraw && this.dataToDraw[this.iterator]) {
                let xStart = this.dataToDraw[this.iterator].xStart
                let xFinish = this.dataToDraw[this.iterator].xFinish
                let yStart = this.dataToDraw[this.iterator].yStart
                let yFinish = this.dataToDraw[this.iterator].yFinish


                const drawStroke = () => {

                    xStart = xStart + (xFinish - xStart) * (this.iterator / 2)
                    yStart = yStart + (yFinish - yStart) * (this.iterator / 2)

                    let x2 = xStart + (xFinish - xStart) * ((this.iterator / 2) + 250)
                    let y2 = yStart + (yFinish - yStart) * ((this.iterator / 2) + 250)

                    const rab = Math.sqrt(Math.pow((x2 - xStart), 2) + Math.pow((y2 - yStart), 2))

                    const gradient = ctx.createLinearGradient(xStart, yStart, x2, y2)
                    gradient.addColorStop(1, this.dataToDraw[this.iterator].rgbaStart)
                    gradient.addColorStop(0, this.dataToDraw[this.iterator].rgbaStop)

                    ctx.strokeStyle = gradient

                    if (rab < 1) return
                    else {

                        ctx.clearRect(0, 0, width, height)
                        ctx.beginPath()
                        // ctx.strokeText('.', xFinish, yFinish)
                        ctx.moveTo(xStart, yStart);
                        ctx.lineTo(x2, y2);
                        ctx.closePath()
                        ctx.stroke();
                    }

                    requestAnimationFrame(drawStroke)

                }

                drawStroke()
            }

            this.iterator++

            requestAnimationFrame(this.animate)

        }
    }

    new Builder()
  • Вопрос задан
  • 87 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 1
twobomb
@twobomb
Если правильно понял, то должно быть типа такого

P.S. Настроить скорость можно через this.animationStep и this.iteratorStep
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы