成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Canvas 點線動畫案例

mykurisu / 1494人閱讀

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

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

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

填充:
fill()
繪制:
stroke()
1、畫一個點
初始化

  瀏覽器不支持canvas!
找到 元素
let canvas = document.getElementById("canvas");
創(chuàng)建 context 對象
let ctx = canvas.getContext("2d");
畫圓
// 坐標(biāo)(x, y)、半徑、開始角度、結(jié)束角度、順時針(逆時針)
ctx.arc(70, 80, 30, 0, Math.PI * 2, false);
2、畫很多點
//生成點
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、畫兩點一線
確定兩個點的坐標(biāo) + lineTo 、moveTo
for (let i = 0; i < 2; i++) {
  ctx.beginPath()
  // 設(shè)置原點位置為(100,100),半徑為10
  ctx.arc(100 + i * 150, 100 + i * 250, 10, 0, Math.PI * 2, false)

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

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

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

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

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

  // 畫點
  this.x;
  this.y;
  this.r;
};
添加一個用于點的生成的初始化方法。
Dots.prototype = {
  // 初始化點的方法
  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();
  }
};
在點與點之間進(jì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,
          // 三角形斜邊長
          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();
      }
    }
  }

點與點之間連線

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

5、requestAnimationFrame

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

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

優(yōu)勢

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

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

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

動效繪制大致路數(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 畫布上繪制圖形的代碼,但是如果僅僅有上面代碼還不夠,如果是同一個位置不斷刷新,我們看到的還是靜止不動的效果,所以還需要一個運(yùn)動變量。

運(yùn)動坐標(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、動起來的多點多線

動的是點,畫的是線

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

  // 畫點
  this.x;
  this.y;
  this.r;

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

    // 點超出 canvas 范圍時重新初始化
    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();
  }
動畫及連線

兼容 requestAnimationFrame

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

或者使用 setTimeout 向下兼容:

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

由于點的位置不斷變換,因此需要將畫線的操作放在動畫內(nèi)執(zhí)行,點的位置 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,
          // 三角形斜邊長
          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);
  }
類似的例子

星空效果、下雨效果等

你可能不知道的點
1、canvas 畫的圓不是圓,是橢圓

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

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

畫新元素前記得要 beginPath()

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

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

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/117514.html

相關(guān)文章

  • 《每周一點canvas動畫》——3D點線與水波動畫

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

    jaysun 評論0 收藏0
  • 《每周一點canvas動畫》——差分函數(shù)的妙用

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

    meislzhua 評論0 收藏0
  • 前端特效demo | 值得收藏的6個 HTML5 Canvas 實用案例

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

    Chao 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<