React中使用Canvas

1. Canvas

  1. Canvas是HTML5新增的组件,它就像一块幕布,可以用JavaScript在上面绘制各种图表、动画等。
    只能够js脚本驱动是Canvas的特点。
  2. canvas元素
<canvas id='mycanvas' width=400 height=400>
    Your browser does not support the canvas element.
</canvas>
  • 支持canvas的浏览器会只渲染canvas标签,而忽略其中的替代内容。不支持 canvas的浏览器则会直接渲染替代内容。
  • 说明canvas内部是不可以嵌套其他dom结构的。
  1. CanvasRenderingContext2D对象
    所有的绘图操作都需要通过这个对象完成。
    image.png
  2. 绘制折线路径
//canvas元素
var c=document.getElementById('mycanvas');
//context对象
var ctx=c.getContext('2d');
ctx.beginPath();
//①定义样式
ctx.strokeStyle='green';        //颜色
ctx.lineWidth=20;               //线宽
ctx.lineCap='square';           //端点
ctx.lineJoin='round';           //拐点
//②定义路径
ctx.moveTo(50,50);      //起点
ctx.lineTo(100,100);        //拐点
ctx.lineTo(50,200);     //终点
ctx.closePath();                //闭合
//③绘制
ctx.stroke();
image.png
  • canvas元素必须通过widthheight设置宽高。重新设置widthheight,画布中任何已绘对象都将被清除。
  • 每一个canvas元素仅有一个context对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法和属性。
  • 定义样式和定义路径(位置尺寸)的相对位置可调整,但绘制必须在定义样式和定义路径(位置尺寸)之后,否则样式和路径无法生效。
  • 若未定义样式,则为默认样式;若未修改样式,则为上次样式。
  1. 绘制其它路径
//矩形路径
//位置(50,20),尺寸(200,200)
ctx.rect(50,20,200,200);
//③绘制
ctx.stroke();

//原型路径
//②定义位置尺寸
//中心点坐标(100,70),半径50,开始角180度,结束角0度,逆时针。
ctx.arc(100,70,50,Math.PI,0,true);
//③绘制
ctx.stroke();
  1. 绘制笑脸
ctx.clearRect(0, 0, 200, 200); // 擦除(0,0)位置大小为200x200的矩形,擦除的意思是把该区域变为透明
ctx.fillStyle = '#dddddd'; // 设置颜色
ctx.fillRect(10, 10, 130, 130); // 把(10,10)位置大小为130x130的矩形涂色
// 利用Path绘制复杂路径:
var path=new Path2D();
path.arc(75, 75, 50, 0, Math.PI*2, true);
path.moveTo(110,75);
path.arc(75, 75, 35, 0, Math.PI, false);
path.moveTo(65, 65);
path.arc(60, 65, 5, 0, Math.PI*2, true);
path.moveTo(95, 65);
path.arc(90, 65, 5, 0, Math.PI*2, true);
ctx.strokeStyle = '#0000ff';
ctx.stroke(path);
image.png
  1. 绘制图片
var img = new Image()
img.src = src
img.onload=function(){
    //剪切位置(0,0),剪切尺寸(600,600),
    //放置位置(0,0),放置尺寸(100,100);
    ctx.drawImage(img,0,0,600,600,0,0,100,100);
}
image.png
  1. canvas动画
var walk = require('../assets/1.jpg');
var img=document.createElement('img');
document.body.appendChild(img)
img.src=walk
img.onload=function(){
    var x=0;
    setInterval(function(){
        ctx.clearRect(0,0,500,500);
        ctx.drawImage(img, x,0,180,400,0,0,180,400);
        x+= 180;
        if (x>=900) {
            x=0
        };
    },100)
};
  1. SVG vs canvas:如何选择
对比 Canvas SVG
操作对象 基于像素 基于图形元素
元素 单个HTML元素 多种图形元素(Rect,Path,Line...)
驱动 脚本驱动 支持脚本和CSS
交互粒度 用户交互到像素点(x, y) 用户交互到图形元素
性能 适合较小面积,较多的对象 适合较少的对象,较大的面积
image.png

2. react-konva

  1. react-konvareact-canvasgithub上星星比较多的react相关canvas第三方库。由于react-canvas173月之后就没有更新了,且不支持react 16,因此不再考虑。这里主要介绍react-konva的使用。
  2. React Konva是一个JavaScript库,用于使用React绘制复杂的画布图形。
  3. 基本概念
    把整个视图看做一个舞台stage。而舞台中的每一层,看做layerlayer层中有许多group组。在group中绘制画图、图片等shape
               Stage
                |
         +------+------+
         |             |
       Layer         Layer
         |             |
   +-----+-----+     Shape
   |           |
 Group       Group
   |           |
   +       +---+---+
   |       |       |
Shape   Group    Shape
           |
           +
           |
         Shape
  1. 示例
import React, { Component } from "react";
import Konva from "konva";
import { render } from "react-dom";
import { Stage, Layer, Rect, Text } from "react-konva";

class ColoredRect extends React.Component {
  state = {
    color: "green"
  };
  handleClick = () => {
    this.setState({
      color: Konva.Util.getRandomColor()
    });
  };
  render() {
    return (
      <Rect
        x={20}
        y={20}
        width={50}
        height={50}
        fill={this.state.color}
        shadowBlur={5}
        onClick={this.handleClick}
      />
    );
  }
}

class App extends Component {
  render() {
    return (
      <Stage width={window.innerWidth} height={window.innerHeight}>
        <Layer>
          <Text text="Try click on rect" />
          <ColoredRect />
        </Layer>
      </Stage>
    );
  }
}

render(<App />, document.getElementById("root"));

参考

学习HTML5 Canvas这一篇文章就够了
Konva入门教程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349