成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Canvas 點(diǎn)線動(dòng)畫案例

mykurisu / 1450人閱讀

摘要:運(yùn)動(dòng)坐標(biāo)變量坐標(biāo)變量繪制方法畫布渲染清除畫布位置變化繪制繼續(xù)渲染動(dòng)起來(lái)的多點(diǎn)多線動(dòng)的是點(diǎn),畫的是線給對(duì)象添加運(yùn)動(dòng)變量和兩個(gè)值表示點(diǎn)在軸和軸的運(yùn)動(dòng)量此處為在之間運(yùn)動(dòng)。

Canvas 點(diǎn)線動(dòng)畫案例
畫圓:
arc(x, y, r, start, stop)
畫線:
moveTo(x, y) 定義線條開始坐標(biāo)

lineTo(x, y) 定義線條結(jié)束坐標(biāo)

填充:
fill()
繪制:
stroke()
1、畫一個(gè)點(diǎn)
初始化

  瀏覽器不支持canvas!
找到 元素
let canvas = document.getElementById("canvas");
創(chuàng)建 context 對(duì)象
let ctx = canvas.getContext("2d");
畫圓
// 坐標(biāo)(x, y)、半徑、開始角度、結(jié)束角度、順時(shí)針(逆時(shí)針)
ctx.arc(70, 80, 30, 0, Math.PI * 2, false);
2、畫很多點(diǎn)
//生成點(diǎn)
for (let i = 0; i < dotsNum; i ++) {
  x = Math.random() * canvas.width;
  y = Math.random() * canvas.height;
  r = Math.random() * 4; // 隨機(jī)生成 <4 的半徑值

  ctx.beginPath();
  ctx.arc(x, y, r, 0, 2 * Math.PI);
  ctx.fillStyle = "rgba(0,0,0,.8)";
  ctx.fill();
  ctx.closePath();
}
3、畫兩點(diǎn)一線
確定兩個(gè)點(diǎn)的坐標(biāo) + lineTo 、moveTo
for (let i = 0; i < 2; i++) {
  ctx.beginPath()
  // 設(shè)置原點(diǎn)位置為(100,100),半徑為10
  ctx.arc(100 + i * 150, 100 + i * 250, 10, 0, Math.PI * 2, false)

  // 兩個(gè)點(diǎn)進(jìn)行畫線
  ctx.moveTo(100, 100)
  ctx.lineTo(100 + i * 150, 100 + i * 250)

  // 設(shè)置線的寬度,單位是像素
  ctx.lineWidth = 2
  ctx.stroke()

  // 實(shí)心圓 - 填充顏色,默認(rèn)是黑色
  // 實(shí)心圓 - 畫實(shí)心圓
  ctx.fill()
  ctx.closePath()
}
4、畫多點(diǎn)多線

當(dāng)點(diǎn)很多、元素很多的時(shí)候再進(jìn)行畫線操作會(huì)很繁瑣,對(duì)于多元素的情況,創(chuàng)建實(shí)例對(duì)象,把變量存儲(chǔ)在實(shí)例對(duì)象上。

定義一個(gè)Dots函數(shù)。
var Dots = function () {
  // 畫布
  this.canvas;
  this.ctx;

  // 畫點(diǎn)
  this.x;
  this.y;
  this.r;
};
添加一個(gè)用于點(diǎn)的生成的初始化方法。
Dots.prototype = {
  // 初始化點(diǎn)的方法
  init: function (canvas) {
    this.canvas = canvas;
    this.ctx = this.canvas.getContext("2d");

    this.x = Math.random() * this.canvas.width;
    this.y = Math.random() * this.canvas.height;
    this.r = Math.random() * 4; // 隨機(jī)生成 <4 的半徑值

    this.ctx.beginPath();
    this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    this.ctx.fillStyle = "black";
    this.ctx.fill();
    this.ctx.closePath();
  }
};
在點(diǎn)與點(diǎn)之間進(jìn)行畫線,每?jī)蓚€(gè)點(diǎn)之間就有一條線,總共有C(n,2)條線。
// 繪制連線
  for (var i = 0; i < dotsNum; i ++) {
    for (var j = i + 1; j < dotsNum; j ++) {
      var tx = dotsArr[i].x - dotsArr[j].x,
          ty = dotsArr[i].y - dotsArr[j].y,
          // 三角形斜邊長(zhǎng)
          s = Math.sqrt(Math.pow(tx, 2) + Math.pow(ty, 2));

      if (s < dotsDistance) {
        ctx.beginPath();
        ctx.moveTo(dotsArr[i].x, dotsArr[i].y);
        ctx.lineTo(dotsArr[j].x, dotsArr[j].y);
        ctx.strokeStyle = "rgba(0,0,0,"+(dotsDistance-s)/dotsDistance+")";

        ctx.strokeWidth = 1;
        ctx.stroke();
        ctx.closePath();
      }
    }
  }

點(diǎn)與點(diǎn)之間連線

優(yōu)化點(diǎn):
限定點(diǎn)與點(diǎn)的連線距離(優(yōu)化:根據(jù)點(diǎn)之間的距離添加連線顏色透明度)

5、requestAnimationFrame

Canvas 畫布的工作原理和顯示器工作原理一樣,都是通過(guò)不斷的刷新繪制。瀏覽器的刷新是實(shí)時(shí)的,而 Canvas 的刷新是手動(dòng)觸發(fā)的,如果我們只想在 Canvas 上實(shí)現(xiàn)靜態(tài)的效果,就沒(méi)必不斷刷新。

requestAnimationFrame是瀏覽器用于定時(shí)循環(huán)操作的一個(gè)接口,類似于setTimeout,主要用途是按對(duì)網(wǎng)頁(yè)進(jìn)行重繪。requestAnimationFrame不是自己指定回調(diào)函數(shù)運(yùn)行的時(shí)間,而是跟著瀏覽器內(nèi)建的刷新頻率來(lái)執(zhí)行回調(diào)。

優(yōu)勢(shì)

瀏覽器可以優(yōu)化并行的動(dòng)畫動(dòng)作,更合理的重新排列動(dòng)作序列,并把能夠合并的動(dòng)作放在一個(gè)渲染周期內(nèi)完成,從而呈現(xiàn)出更流暢的動(dòng)畫效果,一旦頁(yè)面不處于瀏覽器的當(dāng)前標(biāo)簽,就會(huì)自動(dòng)停止刷新。

使用方式
持續(xù)調(diào)用 requestAnimFrame

清除動(dòng)畫調(diào)用 cancelAnimationFrame

動(dòng)效繪制大致路數(shù):
var canvas = document.querySelector("canvas");
var context = canvas.getContext("2d");

// 畫布渲染
var render = function () {
    // 清除畫布
    context.clearRect(0, 0, canvas.width, canvas.height);
    // 繪制(在canvas畫布上繪制圖形的代碼)
    draw();
    // 繼續(xù)渲染
    requestAnimationFrame(render);
};
render();

上面的draw()就是在 canvas 畫布上繪制圖形的代碼,但是如果僅僅有上面代碼還不夠,如果是同一個(gè)位置不斷刷新,我們看到的還是靜止不動(dòng)的效果,所以還需要一個(gè)運(yùn)動(dòng)變量。

運(yùn)動(dòng)坐標(biāo)變量:
var canvas = document.querySelector("canvas");
var context = canvas.getContext("2d");

// 坐標(biāo)變量
var x = 0;
// 繪制方法
var draw = function () {
    ball.x = x;
};
// 畫布渲染
var render = function () {
    // 清除畫布
    context.clearRect(0, 0, canvas.width, canvas.height);
    // 位置變化
    x++;
    // 繪制
    draw();
    // 繼續(xù)渲染
    requestAnimationFrame(render);
};

render();
6、動(dòng)起來(lái)的多點(diǎn)多線

動(dòng)的是點(diǎn),畫的是線

給 Dots 對(duì)象添加運(yùn)動(dòng)變量,sx 和 sy 兩個(gè)值表示點(diǎn)在x軸和y軸的運(yùn)動(dòng)量,此處為在[-2, 2)之間運(yùn)動(dòng)。
let Dots = function () {
  // 畫布
  this.canvas;
  this.ctx;

  // 畫點(diǎn)
  this.x;
  this.y;
  this.r;

  // 移動(dòng)
  // 隨機(jī)確定點(diǎn)的移動(dòng)速度與方向 速度值在 [-2, 2) 之間 提高數(shù)值可加快速度 
  //(Math.random() 隨機(jī)返回[0,1)的數(shù))
  this.sx = Math.random() * 4 - 2;
  this.sy = Math.random() * 4 - 2;
};
添加更新點(diǎn)的方法update()
// 更新點(diǎn)位置
  update: function () {
    this.x = this.x + this.sx;
    this.y = this.y + this.sy;

    // 點(diǎn)超出 canvas 范圍時(shí)重新初始化
    if (this.x < 0 || this.x > this.canvas.width) {
      this.init(this.canvas);
    }
    if (this.y < 0 || this.y > this.canvas.height) {
      this.init(this.canvas);
    }

    this.ctx.beginPath();
    this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    this.ctx.fillStyle = "rgba(0,0,0,.6)";
    this.ctx.fill();
    this.ctx.closePath();
  }
動(dòng)畫及連線

兼容 requestAnimationFrame

  let requestAnimFrame = requestAnimationFrame || webkitRequestAnimationFrame || oRequestAnimationFrame || msRequestAnimationFrame;
  requestAnimFrame(animateUpdate); // 兼容不同瀏覽器的 requestAnimationFrame

或者使用 setTimeout 向下兼容:

// requestAnimationFrame的向下兼容處理
if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = function(fn) {
        setTimeout(fn, 17);
    };
}

由于點(diǎn)的位置不斷變換,因此需要將畫線的操作放在動(dòng)畫內(nèi)執(zhí)行,點(diǎn)的位置 update 一次就執(zhí)行一次連線。

  function animateUpdate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空canvas中原有的內(nèi)容

    for (let i = 0; i < dotsNum; i ++) {
      dotsArr[i].update();
    }

    // 繪制連線
    for (let i = 0; i < dotsNum; i ++) {
      for (let j = i + 1; j < dotsNum; j ++) {
        let tx = dotsArr[i].x - dotsArr[j].x,
          ty = dotsArr[i].y - dotsArr[j].y,
          // 三角形斜邊長(zhǎng)
          s = Math.sqrt(Math.pow(tx, 2) + Math.pow(ty, 2));
        if (s < dotsDistance) {
          ctx.beginPath();
          ctx.moveTo(dotsArr[i].x, dotsArr[i].y);
          ctx.lineTo(dotsArr[j].x, dotsArr[j].y);
          ctx.strokeStyle = "rgba(0,0,0,"+(dotsDistance-s)/dotsDistance+")";
          ctx.strokeWidth = 1;
          ctx.stroke();
          ctx.closePath();
        }
      }
    }
    // 繼續(xù)渲染
    requestAnimFrame(animateUpdate);
  }
類似的例子

星空效果、下雨效果等

你可能不知道的點(diǎn)
1、canvas 畫的圓不是圓,是橢圓

不要在style里指定 Canvas 的寬度,Canvas 畫布的尺寸的大小和顯示的大小是有很大的區(qū)別的,在 canvas 里面設(shè)置的是才是 Canvas 本身的大小。

如果不給設(shè)置 width、height 屬性時(shí),則默認(rèn) width 為 300、height 為 150, 單位都是 px。也可以使用 css 屬性來(lái)設(shè)置寬高,但是如寬高屬性和初始比例不一致,他會(huì)出現(xiàn)扭曲。所以,建議永遠(yuǎn)不要使用css屬性來(lái)設(shè)置的寬高。
2、不要企圖通過(guò)閉合現(xiàn)有路徑來(lái)開始一條新路徑

畫新元素前記得要 beginPath()

不管用 moveTo 把畫筆移動(dòng)到哪里,只要不調(diào)用beginPath(),一直都是在畫一條路徑

fillRect 與 strokeRect 這種直接畫出獨(dú)立區(qū)域的函數(shù),也不會(huì)打斷當(dāng)前的path

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/117514.html

相關(guān)文章

  • 《每周一點(diǎn)canvas動(dòng)畫》——3D點(diǎn)線與水波動(dòng)畫

    摘要:在數(shù)學(xué)上,遞推關(guān)系,也就是差分方程,是一種遞推地定義一個(gè)序列的方程式序列的每一項(xiàng)目是定義為前一項(xiàng)的函數(shù)。 《每周一點(diǎn)canvas動(dòng)畫》——差分函數(shù)的妙用 每周一點(diǎn)canvas動(dòng)畫代碼文件 好像上次更新還是十一前,這唰唰唰的就過(guò)去大半個(gè)月了,現(xiàn)在才更新實(shí)在不好意思。這次我們不涉及canvas 3D的內(nèi)容,主要分享一個(gè)比較炫的動(dòng)畫效果,可以算是上一篇文章《每周一點(diǎn)canvas動(dòng)畫》——3D...

    jaysun 評(píng)論0 收藏0
  • 《每周一點(diǎn)canvas動(dòng)畫》——差分函數(shù)的妙用

    摘要:在數(shù)學(xué)上,遞推關(guān)系,也就是差分方程,是一種遞推地定義一個(gè)序列的方程式序列的每一項(xiàng)目是定義為前一項(xiàng)的函數(shù)。某些簡(jiǎn)單定義的遞推關(guān)系式可能會(huì)表現(xiàn)出非常復(fù)雜的混沌的性質(zhì),他們屬于數(shù)學(xué)中的非線性分析領(lǐng)域。 每周一點(diǎn)canvas動(dòng)畫代碼文件 好像上次更新還是十一前,這唰唰唰的就過(guò)去大半個(gè)月了,現(xiàn)在更新我也沒(méi)什么不好意思的。這次我們不涉及canvas 3D的內(nèi)容,主要分享一個(gè)比較炫的動(dòng)畫效果,可以算...

    meislzhua 評(píng)論0 收藏0
  • 前端特效demo | 值得收藏的6個(gè) HTML5 Canvas 實(shí)用案例

    摘要:模擬飛機(jī)航班線路動(dòng)畫一款基于的飛機(jī)航班線路模擬動(dòng)畫,它模擬了許多航班在不同目的地的起飛降落數(shù)量。跳動(dòng)加載動(dòng)畫可調(diào)節(jié)參數(shù)這是一款基于的跳動(dòng)加載動(dòng)畫,它的另一個(gè)特點(diǎn)是可以動(dòng)態(tài)調(diào)節(jié)動(dòng)畫參數(shù)。 showImg(https://segmentfault.com/img/bVblze6?w=900&h=383); HTML5 動(dòng)畫在Canvas 上得到了充分的發(fā)揮,我們 VIP 視頻也分享過(guò)很多相...

    Chao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<