前端初學基礎知識 3

canvas動畫

       動畫的造成:先畫出一幅圖,改變其中的一些參數,從新繪製圖片...不斷的重複造成動畫。javascript

  • fillStyle:設置或返回填充繪畫的顏色,漸變或模式
  • strokeStyle:設置或返回用於筆觸的顏色,漸變或模式
  • fill(): 填充當前路徑(若是路徑未關閉則會從路徑結束點到開始點之間添加一條線)
  • stroke():繪製已定義的路徑。
  • moveTo():把路徑移動到畫布中的指定點,不建立線條
  • beginPath():起始一條路徑或重置當前路徑
  • closePath():建立從當前點回到起始點的路徑
  • lineTo():添加一個新點,建立一條鏈接至該點的線條
  • clearRect():清除指定矩形內的像素
  • arc():建立弧或曲線
  • rotate():建立兩點之間的弧或曲線
  • translate():從新映射畫布上的(0,0)位置
  • drawImage():繪製圖像、畫布或視頻
  • save():保存當前環境狀態
  • restore():返回以前保存過的路徑和狀態
  • getContext():返回一個用於在畫布上繪圖的環境
  • requestAnimationFrame():回調例程調用 requestAnimationFrame()。根據瀏覽器設備的繪製限制,來更新動畫,回調的次數常是每秒60次。

canvas學習——樹鏡

總體邏輯
  1. 建立一個類,實例化根元素,遞歸建立分支直到層數,每層分支長度(length)遞減,直至層數>=5;
  2. 調用drawBranch生成一張圖片
  3. 改變樹枝展開角度以及位置執行requestA nimationFrame();重複執行;造成動畫
  4. 將12個不一樣旋轉角度的動畫canvas添加到canvas2.圍成一圈。
  5. 鼠標移入則中止自動改變樹枝狀態,轉爲由鼠標的橫縱座標控制。
關鍵代碼理解
class Branch {
    /**
     * 分枝類,如下爲參數,都帶有默認值
     * 位置 position
     * 長度 length
     * 分支位置 divergeAt
     * 展開角度 angle
     * 層數 depth
     * 分支展開角度變化量 spread
     */
  constructor(position = {x : 0, y: 0}, length = 100, divergeAt = 0.5, angle = 0, depth = 0, spread = 45 * TO_RADIAN) {
    this.position = position;
    this.length = length;
    this.divergeAt = divergeAt;
    this.angle = angle;
    this.depth = depth;

    this.color = '#000';
    this.spread = spread;
    this.branches = [];

    this.grow();
  }

  grow() {
      /**
       * 建立分支,若是canBranch = true(未達到最大分支數量)
       * 新分支長度爲父級的0.75,深度加1
       * 展開角度變化spread
       * 因爲構造方法中調用了grow方法,因此會不斷重複建立上述過程
       */
    if (!this.canBranch) {
      return;
    }

    this.branches = [];

    const nextLength = this.length * 0.75;
    const nextDepth = this.depth + 1;

    this.branches.push(
      new Branch(
        this.growPosition,
        nextLength,
        this.divergeAt,
        this.angle + this.spread,
        nextDepth,
        this.spread
      ),
      new Branch(
        this.growPosition,
        nextLength,
        this.divergeAt,
        this.angle - this.spread,
        nextDepth,
        this.spread
      )
    );
  }

  update(spread, divergeAt) {
    this.spread = spread;
    this.divergeAt = divergeAt;

    this.grow();
  }

  get growPosition() {
    const dl = this.length * this.divergeAt;

    return {
      x: this.position.x + (Math.cos(this.angle) * dl),
      y: this.position.y + (Math.sin(this.angle) * dl),
    };
  }

  get canBranch() {
    return this.depth < maxDepth;
  }
}
/**
     * 保存當前狀態
     * 根據branch類中的數據畫圖(顏色,直線和圓點)
     * 遞歸對分支進行繪圖
     */
const drawBranch = (branch, phase) => {
  const h = ~~(200 + (160 * phase));
  const l = 50 + ~~(((branch.depth / (maxDepth + 1))) * 50);

  const endX = branch.length;
  const endY = 0;
  const r = 2;

  ctx.save();

  ctx.strokeStyle = `hsl(${h}, 100%, ${l}%)`;
  ctx.translate(branch.position.x, branch.position.y);
  ctx.rotate(branch.angle);

  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.lineTo(endX, endY);
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.fillStyle = `hsl(${h}, 100%, 50%)`;
  ctx.arc(endX, endY, r, 0, PI * 2, false);
  ctx.fill();
  ctx.closePath();

  ctx.restore();

  branch.branches.forEach((b) => {
    drawBranch(b, phase);
  });
};
const loop = () => {
    /**
     * 改變類中參數的值
     * 將第一個canvas添加到在第二個canvas中循環12次每次旋轉2PI/12的角度,造成一個環狀
     * 調用requestAnimationFrame() 從新根據類中的數據畫圖
     */
  let phase = rootBranch.spread / maxSpread;

  clear(phase);

  if (autoAnimate) {
    phase = map(Math.sin(autoTick), -1, 1, 0, 1);

    spread = phase * maxSpread;
    divergeAt = map(Math.sin(autoTick), -1, 1, 0, 0.5);

    autoTick += autoSpeed;
  }

  rootBranch.update(spread, divergeAt);

  drawBranch(rootBranch, phase);

  const numSegments = 12;
  const angleInc = PI * 2 / numSegments;
  let angle = tick;

  for (let i = 0; i < numSegments; i++) {
    ctx2.save();
    ctx2.translate(midX, midY);
    ctx2.rotate(angle);
    ctx2.drawImage(canvas, -w / 2, -h / 2);
    ctx2.restore();
    angle += angleInc;
  }

  tick += 0.002;

  requestAnimationFrame(loop);
};

element-ui

安裝

  • npm安裝: npm i element-ui -s
  • cdn

引入

完整引入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
按需引入

須要安裝 babel-plugin-component:css

npm install babel-plugin-component -D

在.babelrc中添加:vue

"plugins": [
    "transform-vue-jsx", "transform-runtime",
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
import {Loading, Tabs, TabPane,} from 'element-ui';

Vue.use(Loading);
Vue.use(Tabs);
Vue.use(TabPane);

自定義主題

在項目中直接改變scss變量

/* 改變主題色變量 */
$--color-primary: teal;

/* 改變 icon 字體路徑變量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';

@import "~element-ui/packages/theme-chalk/src/index";

命令行主題工具

npm i element-theme -g

以後步驟爲:java

  1. 安裝主題
  2. 初始化變量文件
  3. 修改變量
  4. 編譯成css
  5. 引入

JavaScript 對象的深拷貝

       在星盤改版的時候遇到了相關的問題,數據從父組件傳遞到子組件,當時沒考慮到這方面的問題,只是對數據進行了一層的拷貝,由於當時傳進來的數據是有不少層的,因此仍是會致使源數據改變。因此總結一下,寫成一個方法,這個應該會比較經常使用。es6

       Object屬於引用類型,對它進行簡單賦值(obj1 = obj2)的話只是建立一個指針指向原數據的地址,改變它的值也會改變源數據的值,會形成不少問題。npm

基本的深拷貝方法

數組

concat,slice 等方法,es6 新增運算符‘...’element-ui

對象

思路是把對象拆開分別賦值,一樣可使用es6 新增運算符‘...’,for循環等。canvas

深拷貝的實現

運用遞歸逐層拷貝。數組

function depCopy(obj){
    let value;
    if(typeof obj === "object"){
      if(Object.prototype.toString.call(obj).slice(8,-1)==='Array'){
        // debugger;
        value = [];
        for(let i = 0, length = obj.length; i<length; i++){
          value.push(depCopy(obj[i]));
        }
      }
      else{
        value = {};
        for(let j in obj){
          value[j] = depCopy(obj[j]);
        }
      }
    }
    else{
      value = obj;
    }
    return value;
  }
相關文章
相關標籤/搜索