【问题标题】:Apply Gradient to Canvas and moving balls将渐变应用于画布和移动球
【发布时间】:2018-10-05 23:59:34
【问题描述】:

尝试对我的画布应用线性渐变,它正在移动球,但我不知道我哪里出错了,因为没有任何变化。我试图每次都在加载时应用随机颜色和随机角度。当我创建线性渐变时,我认为问题出在我的 onload 函数中

var $ = function(id) {return document.getElementById(id);};

var bounce;
var my_canvas;
var ball_array = new Array();
var linear_gradient;
var timer; //global variable to keep current timer

function randomGradient()
{
var color1 = randomColor(); //color 1
var color2 = '#FFFFFF'; //color 2
var gradient_angle = Math.round(Math.random()*360);
var random_gradient = "linear-gradient(" + gradient_angle + "deg, " + color1 + ", " + color2 + ")";
return random_gradient;
}

function ball(){
this.x=Math.random()*my_canvas.canvas.width;
this.y=Math.random()*my_canvas.canvas.height;
this.vx = (Math.random()-0.5);
this.vy = (Math.random()-0.5);
 this.color = randomGradient();
 this.radius = 12;
this.move=ball_move;
this.draw=ball_draw;
 }
 function ball_draw(){                    
 my_canvas.save();
 my_canvas.fillStyle=this.color; //****
 my_canvas.strokeStyle='black';
 my_canvas.lineWidth=2;
 my_canvas.beginPath();
my_canvas.arc(this.x, this.y, this.radius,0, 6.28, false);
 my_canvas.closePath();
 my_canvas.stroke();
 my_canvas.fill();
 my_canvas.restore();
 }

 function create_balls(){
 for(var i=0;i<75;i++){
    var temp=new ball();
    ball_array.push(temp);
 }
 }
    function resize_can(){
my_canvas.canvas.width = window.innerWidth/2;
my_canvas.canvas.height = window.innerHeight/2;
    }

    window.onload = function() {
    bounce = -1;
    my_canvas = $("myCanvas").getContext('2d');
    linear_gradient = my_canvas.createLinearGradient(0,0,window.innerWidth / 2,window.innerHeight / 2); //create linear gradient
    window.onresize = resize_can;
    resize_can(); 
    create_balls();
    timer = setInterval(going,5);
  };

【问题讨论】:

    标签: javascript animation canvas gradient


    【解决方案1】:

    你需要用画布创建渐变,不能只使用线性渐变 CSS 字符串

    ctx.fillStyle = "linear-gradient(50%, red, blue)";  // WON'T WORK!
    

    使用

    const gradient = ctx.createLinearGradient(0, 0, width, height);
    gradient.addColorStop(0, "black");
    gradient.addColorStop(1, "white");
    

    最重要的是,渐变是相对于原点的,所以如果你想让渐变保持相对于圆圈,你需要在绘制时平移原点。换句话说,而不是

    ctx.arc(x, y, ...)
    

    你需要

    ctx.translate(x, y);
    ctx.arc(0, 0, ...)
    

    请注意,对于“现代”的某些定义,我将您的代码更改为更现代的 JS。示例,在适当的情况下使用constlet,从不使用var,使用class,使用requestAnimationFrame,计算帧之间的增量时间并使动画帧速率独立,使用querySelector 而不是@ 987654332@,使用[] 而不是new Array,摆脱window.onload(将脚本放在文件末尾或使用defer),使用ctx vs my_canvas(@987654339 没有问题@ 除非它不是“画布”,而是“画布上下文”,或者更具体地说是 CanvasRenderingContext2D

    const $ = function(selector) {
      return document.querySelector(selector);
    };
    
    const ctx = $("#myCanvas").getContext('2d');
    const ball_array = [];
    
    function randomColor() {
      return `hsl(${Math.random() * 360}, 100%, 50%)`;
    }
    
    function randomGradient(size) {
      const gradient = ctx.createLinearGradient(-size, 0, size, 0);
      gradient.addColorStop(0, randomColor());
      gradient.addColorStop(1, '#FFFFFF');
      return gradient;
    }
    
    // JS style, constructors are always Capitalized
    class Ball {
      constructor() {
        this.x = Math.random() * ctx.canvas.width;
        this.y = Math.random() * ctx.canvas.height;
        this.vx = (Math.random() - 0.5) * 50;
        this.vy = (Math.random() - 0.5) * 50;
        this.radius = 12;
        this.color = randomGradient(this.radius);
        this.angle = Math.random() * Math.PI * 2;
      }
    
      draw() {
        ctx.save();
        ctx.fillStyle = this.color; //****
        ctx.strokeStyle = 'black';
        ctx.lineWidth = 2;
        ctx.translate(this.x, this.y);
        ctx.rotate(this.angle);  // because you wanted the gradient at a random angle
        ctx.beginPath();
        ctx.arc(0, 0, this.radius, 0, 6.28, false);
        ctx.closePath();
        ctx.stroke();
        ctx.fill();
        ctx.restore();
      }
    
      move(deltaTime) {
        // you didn't provide this code so I made something up.
        this.x = (this.x + this.vx * deltaTime + ctx.canvas.width) % ctx.canvas.width;
        this.y = (this.y + this.vy * deltaTime + ctx.canvas.height) % ctx.canvas.height;
      }
    };
    
    let then = 0;
    function going(now) {
      now *= 0.001;  // convert to seconds
      const deltaTime = now - then;
      then = now;
    
      ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
      ball_array.forEach((ball) => {
        ball.move(deltaTime);
        ball.draw();
      });
      requestAnimationFrame(going);      
    }
    
    function create_balls() {
      for (let i = 0; i < 75; i++) {
        const temp = new Ball();
        ball_array.push(temp);
      }
    }
    
    function resize_can() {
      ctx.canvas.width = window.innerWidth / 2;
      ctx.canvas.height = window.innerHeight / 2;
    }
    
    window.onresize = resize_can;
    resize_can();
    create_balls();
    
    requestAnimationFrame(going);
    &lt;canvas id="myCanvas"&gt;&lt;/canvas&gt;

    【讨论】:

    • 很好,但如果您只想save() 是变换矩阵,最好直接使用绝对的setTransform(),而不是保存所有上下文的属性并为每个球。而闭合弧(即圆)上的 closePath 没有任何好处。
    【解决方案2】:

    您需要填充画布并选择渐变颜色。

    类似:

    my_canvas = $("myCanvas").getContext('2d');
    var linear_gradient = my_canvas.createLinearGradient(0,0,window.innerWidth / 2,window.innerHeight / 2);
    linear_gradient.addColorStop(0, "black");
    linear_gradient.addColorStop(1, "white");
    
    my_canvas.fillStyle = linear_gradient;
    my_canvas.fillRect(0,0,100,100);
    

    【讨论】:

      猜你喜欢
      • 2020-03-31
      • 1970-01-01
      • 2023-03-08
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 1970-01-01
      相关资源
      最近更新 更多