Javascript:五彩纸屑颗粒落在画布上

时间:2017-10-23 13:36:49

标签: javascript canvas transform skew

我发现这个伟大的剧本让它下雨五彩纸屑:http://jsfiddle.net/hcxabsgh/ 注意粒子如何具有这种扭曲/转动/歪斜效果,使其感觉更自然。

我一直在尝试使粒子圆形也能很好地运作:http://jsfiddle.net/rqr9hb7x/2/

但是我不能像在矩形示例中那样使粒子围绕它们的轴扭曲/转动/倾斜。

我认为它应该可以使用ctx.setTransform(),因为它处理偏斜参数,但它似乎倾斜整个画布而不是单个粒子。有人知道如何妥善处理这个问题吗?

this.draw = function () {
    ctx.beginPath();
    ctx.save();
    //ctx.setTransform(1, 0, 0, 1, 0, 0); // straigt
    ctx.setTransform(1, .3, 0, .7, 0, 0); // skewed - to make dynamic
    ctx.arc(this.x + this.tilt, this.y + this.tilt + (this.r / 4), (this.r / 2), 0, Math.PI * 2, false);
    ctx.restore();
    ctx.fillStyle = this.color;
    return ctx.fill();
}

1 个答案:

答案 0 :(得分:2)

使用$path = "assets/adminlte/dist/img/user2-160x160"; $asd = explode( '/', $path ); $num = count($asd)-1; $arr = []; for($i=0;$i<count($asd);$i++) { for($j=0;$j<=$i;$j++){ @$arr[$i] .= "/".$asd[$j]; } } echo "\n"; print_r($arr);

歪斜

您希望随时间旋转粒子局部x轴。 x轴是setTransform的前两个参数。要随时间旋转该轴,请使用setTransformcos(angle)设置x轴的x和y分量。

如果您希望粒子是局部的,您还需要设置粒子原点(旋转点),然后将粒子绘制在0,0。原点是sin(angle)

的最后两个参数

你想要的绘图功能是

setTransform

实施例

查看给出的小提琴的代码,我无法弄清楚他们想要做什么,因为它过于复杂,所以我重写了整个事情,现在需要第3个代码而不是jQuery。

为您追求的FX运行演示......

也许????

draw() {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.setTransform(
        Math.cos(this.tiltAngle),  // set the x axis to the tilt angle
        Math.sin(this.tiltAngle),
        0, 1, 
        this.x, this.y    // set the origin
    ); 
    ctx.arc(0, 0, (this.r / 2), 0, Math.PI * 2, false); // draw at origin (0,0)
    ctx.fill();
}
(function () {
    requestAnimationFrame(mainLoop);
    const ctx = canvas.getContext("2d");
    var W,H;
    var confetti = new Particles();
    var droppedCount = 0;
    var particlesPerFrame = 1.5;
    var wind = 0;
    var windSpeed = 1; 
    const windSpeedMax = 1;
    const windChange = 0.01;
    const windPosCoef = 0.002;
    const maxParticlesPerFrame = 2; //max particles dropped per frame
    var id = 0;
    stopButton.addEventListener("click",() => particlesPerFrame = 0 );
    startButton.addEventListener("click",() => particlesPerFrame = maxParticlesPerFrame);
		const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
		const rand  = (min = 1, max = min + (min = 0)) => Math.random() * (max - min) + min;    
    const colors = {
        options: "DodgerBlue,OliveDrab,Gold,pink,SlateBlue,lightblue,Violet,PaleGreen,SteelBlue,SandyBrown,Chocolate,Crimson".split(","),
        index: 0,
        step: 10,
        get color() { return colors.options[((colors.index++) / colors.step | 0) % colors.options.length] }
    }
    function Confetti() { this.setup() }
    Confetti.prototype = {
        setup(){        
            this.x = rand(-35,W + 35);
            this.y = rand(-30,-35);
            this.r = rand(10, 30); 
            this.d = rand(150) + 10; //density;
            this.color = colors.color;
            this.tilt = randI(10);
            this.tiltAngleIncremental = (rand(0.08) + 0.04) * (rand() < 0.5 ? -1 : 1);
            this.tiltAngle = 0;
            this.angle = rand(Math.PI * 2);
            this.id = id++;
            return this;
        },
        update() {
            this.tiltAngle += this.tiltAngleIncremental * (Math.cos(wind + (this.d + this.x + this.y) * windPosCoef) * 0.2 + 1);
            this.y += (Math.cos(this.angle + this.d) + 3 + this.r / 2) / 2;
            this.x += Math.sin(this.angle);
            this.x += Math.cos(wind + (this.d + this.x + this.y) * windPosCoef) * windSpeedMax;
            this.y += Math.sin(wind + (this.d + this.x + this.y) * windPosCoef) * windSpeedMax;
            this.tilt = (Math.sin(this.tiltAngle - (this.id / 3))) * 15;
            return this.y > H;  // returns true if particle is past bottom
        },
        draw() {
            ctx.fillStyle = this.color;
            ctx.beginPath();
            ctx.setTransform(
                Math.cos(this.tiltAngle),  // set the x axis to the tilt angle
                Math.sin(this.tiltAngle),
                0, 1,  
                this.x, this.y    // set the origin
            ); 
            ctx.arc(0, 0, (this.r / 2), 0, Math.PI * 2, false);
            ctx.fill();
        }
    }
    function Particles() {
        const items = [];
        const pool = [];
        this.update = function() {
            for (var i = 0; i < items.length; i++) {
                if(items[i].update() === true){ pool.push(items.splice(i--,1)[0]) }
            }            
        }
        this.draw = function() { for (var i = 0; i < items.length; i++) { items[i].draw()  } }
        this.add = function() {
            if (pool.length > 0) { items.push(pool.pop().setup()) }
            else { items.push(new Confetti()) }
        }
    }
    function mainLoop(time) {
        if (W !== innerWidth || H !== innerHeight) {
            W = canvas.width = innerWidth;
            H = canvas.height = innerHeight;
        } else {
            ctx.setTransform(1,0,0,1,0,0);
            ctx.clearRect(0, 0, W, H);
        }
        windSpeed = Math.sin(time / 8000) * windSpeedMax;
        wind += windChange;
        while(droppedCount < particlesPerFrame){
           droppedCount += 1;
           confetti.add();
        }
        droppedCount -= particlesPerFrame;
        confetti.update();
        confetti.draw();
        requestAnimationFrame(mainLoop);
    }
})();
* {
  margin: 0;
  padding: 0;
}

body {
  /*You can use any kind of background here.*/
  background: transparent;
}

canvas {
  display: block;
  position: relative;
  zindex: 1;
  pointer-events: none;
}

#content {
  text-align: center;
  width: 500px;
  height: 300px;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-left: -250px;
  margin-top: -150px;
  color: silver;
  font-family: verdana;
  font-size: 45px;
  font-weight: bold;
}

.buttonContainer {
  display: inline-block;
}

button {
  padding: 5px 10px;
  font-size: 20px;
}

注意部分代码和内容已从this fiddle复制。