• HTML5 canvas绘图基础(电子名片生成器源码)


    创建canvas

      <canvas id="myCanvas" class="canvas">
        您的浏览器不支持canvas
      </canvas>

    基础设置

        <script type="text/javascript">
            var canvas = document.getElementById('myCanvas');
            var ctx = canvas.getContext('2d');
            canvas.width=100;
            canvas.height=100;
        </script>

    画直线
    moveTo(x1, y1)
    lineTo(x2, y2)

        ctx.moveTo(0, 0);
        ctx.lineTo(100, 100);
        ctx.stroke();

    画圆形
    ctx.arc(x,y,radius,0,2*Math.PI,true)

        ctx.beginPath();
        ctx.arc(300,300,50,0,2*Math.PI,true);
        ctx.strokeStyle = '#000';
        ctx.stroke();

    画矩形
    ctx.strokeRect(x1, y1,x2, y2)

        ctx.strokeRect(300,100,200,100);

    beginPath()开始一条新路径
    closePath()使当前路径闭合
    不是成对出现的

          ctx.beginPath();
          ctx.moveTo(300, 0);
          ctx.lineTo(200, 100);
          ctx.lineTo(200, 200);
          ctx.closePath();
          ctx.strokeStyle = '#0F0';
          ctx.stroke();

    设置样式

          ctx.moveTo(0,0);
          ctx.lineTo(100,100);
          ctx.lineTo(100,200);
          ctx.closePath();
          //lineWidth 设置描边的线宽
          ctx.lineWidth = 10;
          //strokeStyle 设置描边样式
          ctx.strokeStyle = "#F00";
          ctx.stroke();
          //fillStyle 设置填充样式
          ctx.fillStyle = "rgba(0,255,0,0.5)";
          ctx.fill();

    绘制矩形与样式同步

          ctx.strokeRect(100,200,100,100);
          ctx.fillRect(100,200,100,100);

    保存和恢复上下文环境,一般成对出现
    save 保存当前绘画环境,包括变换和样式
    restore 恢复当前绘画环境,包括变换和样式

       ctx.save();
       ctx.restore();

    图形变换

          //translate 平移变换
          ctx.translate(0,100);
          ctx.beginPath();
          ctx.moveTo(0,0);
          ctx.lineTo(100,100);
          ctx.stroke();
    
          //rotate 旋转变换
          ctx.rotate(Math.PI/4);
          ctx.beginPath();
          ctx.moveTo(0,0);
          ctx.lineTo(100,100);
          ctx.lineWidth = 5;
          ctx.strokeStyle = "#F00";
          ctx.stroke();
    
          //scale 缩放变换
          ctx.scale(1,0.5);
          ctx.fillRect(0,-100,100,100);

    线性渐变

            var linearGradient = ctx.createLinearGradient(0, 0, 200, 0);
            //给渐变添加颜色
            linearGradient.addColorStop(0, 'rgb(255,0,0)');
            linearGradient.addColorStop(0.3, 'rgb(0,255,0)');
            linearGradient.addColorStop(1, 'rgb(0,0,255)');
            //设置渐变作为样式
            ctx.fillStyle = linearGradient;
            ctx.fillRect(0, 0, 200, 200);

    径向渐变

            var radialGradient = ctx.createRadialGradient(400, 50, 0, 400, 150, 100);
            radialGradient.addColorStop(0, 'rgb(255,255,0)');
            radialGradient.addColorStop(1, 'rgb(0,0,0)');
            ctx.fillStyle = radialGradient;
            ctx.beginPath();
            ctx.arc(400, 150, 100, 0, Math.PI * 2, true);
            ctx.fill();

    文字

    字体若设置了居中,圆心会在文字的中间位置,所以圆心还是要根据画布大小和文字的宽度进行设置。

            var str = "hello world";
            //设置文本样式,比如大小,字体
            ctx.font = "50px sans-serif";
            //水平对其设置,left center right
            ctx.textAlign = "center";
            //垂直对齐设置,top middle bottom
            ctx.textBaseline = "top";
            //填充文本
            ctx.fillText(str,300,0);
            //描边文本
            ctx.strokeText(str,0,200);
            //获取文本宽度
            var width = ctx.measureText(str).width;
            console.log(width);

    图片

            ctx.fillRect(0, 0, canvas.width, canvas.height);
            var img = new Image();
            img.src = "logo.png";
            //一定要在图像加载完成后的回调中绘制图像
            img.onload = function () {
                //在(0,0)点处绘制img图像
                // ctx.drawImage(img, 0, 0);
                //在(0,0)点处绘制img图像,缩放成256*80
                // ctx.drawImage(img, 0, 0, 256, 80);
                //获取img图像的(0,0)点处的40*40区域,绘制在(100,100)点处,缩放成80*80
                ctx.drawImage(img, 0, 0, 40, 40, 100, 100, 80, 80);
            }

    创建图像画刷ctx.createPattern(image, type)

            ctx.fillRect(0, 0, canvas.width, canvas.height);
            var img = new Image();
            img.src = "logo.png";
            img.onload = function () {
                //创建图像画刷,no-repeat,repeat-x,repeat-y,repeat
                var pattern = ctx.createPattern(img, "repeat");
                ctx.fillStyle = pattern;
                ctx.fillRect(0, 0, canvas.width, canvas.height);
            }

    阴影绘制

            //阴影的X偏移
            ctx.shadowOffsetX = 10;
            //阴影的Y偏移
            ctx.shadowOffsetY = 10;
            //阴影的颜色
            ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
            //阴影的模糊度
            ctx.shadowBlur = 10;
            ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
            ctx.fillRect(100, 100, 100, 100);
    
            ctx.font = "50px sans-serif";
            ctx.fillText("我是小可爱",200,100);

    区域剪辑

        //保存当前环境
        ctx.save();
        ctx.arc(300, 100, 200, 0, Math.PI*2, true);
        //进行区域剪辑
        ctx.clip();
        ctx.fillStyle = "#F00";
        ctx.fillRect(100, 100, 200, 200);
        //恢复环境,释放了剪辑区域的作用
        ctx.restore();

    绘制曲线ctx.arc(x, y, startAngle, endAngle ,Math.PI*2, true)
    最后一个参数代表是否是逆时针方向

            //绘制圆弧
            ctx.arc(100, 100, 50, 0 ,Math.PI*2, true);
            ctx.fill();
    
            //二次样条曲线ctx.quadraticCurveTo(qcpx,qcpy,qx,qy)
            ctx.beginPath();
            ctx.moveTo(100,355);
            ctx.quadraticCurveTo(265,145,380,349);
            ctx.fill();
    
            //贝塞尔曲线ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)
            ctx.beginPath();
            ctx.moveTo(175,375);
            ctx.bezierCurveTo(297,182,468,252,517,380);
            ctx.fill();

    canvas绘制曲线生成工具
    两次贝塞尔曲线:
    http://blogs.sitepointstatic.com/examples/tech/canvas-curves/quadratic-curve.html
    三次贝塞尔曲线:
    http://blogs.sitepointstatic.com/examples/tech/canvas-curves/bezier-curve.html


    动画

    ctx.clearRect(x, y, width, height) 清除区域,用于重新绘制

            var canvas = document.getElementById('myCanvas');
            var ctx = canvas.getContext('2d');
            var posx = 0, posy = 0, dir = 1, isMouseInRect = false;
    
            // 确定动画范围
            canvas.onmousemove = function(e){
                var mouseX = e.offsetX;
                var mouseY = e.offsetY;
                if(mouseX > posx && mouseY <posx +50 && mouseY > posy && mouseY < posy+ 50){
                    isMouseInRect = true;
                }else{
                    isMouseInRect = false;
                }
            }
    
            // 开始动画
            setInterval(function() {
                if(!isMouseInRect){
                    posx += 10 * dir;
                }
                //clearRect清空画布的一个矩形区域
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.fillRect(posx, posy, 50, 50);
                if(posx + 50 >= canvas.width){
                    dir = -1;
                }else if(posx <= 0){
                    dir = 1;
                }
            },100);

    离屏技术
    把canvas(sx,sy)处宽sw,高sy的区域,绘制到(dx,dy)处,并缩放为宽dx,高dh
    ctx.drawImage(canvas,sx,sy,sw,sh,dx,dy,dw,dh)

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <title>canvas</title>
      <style type="text/css">
        canvas {
          border: 1px solid red;
        }
        #offCanvas{
          display: none;
        }
      </style>
    </head>
    <body>
        <canvas id="myCanvas"  width="600px" height="400px">
          您的浏览器不支持canvas
        </canvas>
        <!--创建离屏Canvas-->
        <canvas id="offCanvas"  width="600px" height="400px">
          您的浏览器不支持canvas
        </canvas>
        <script  type="text/javascript">
            var canvas = document.getElementById('myCanvas');
            var ctx = canvas.getContext('2d');
    
            var offCanvas = document.getElementById('offCanvas');
            var offCtx = offCanvas.getContext('2d');
    
            var posx = 0, posy = 0, dir = 1, isMouseInRect = false;
    
            //把一些复杂的绘画操作,画在离屏Canvas上面
            var drawALot = function(){
                for(var k=0; k<20; k++){
                    for(var i=0;i<canvas.width;i+=10){
                        for(var j=0;j<canvas.height;j+=10){
                            offCtx.beginPath();
                            offCtx.arc(i,j,5,0,2*Math.PI,true);
                            offCtx.stroke();
                        }
                    }
                }
            }
    
            canvas.onmousemove = function(e){
                var mouseX = e.offsetX;
                var mouseY = e.offsetY;
                if(mouseX > posx && mouseY <posx +50 && mouseY > posy && mouseY < posy + 50){
                    isMouseInRect = true;
                }else{
                    isMouseInRect = false;
                }
            }
    
            setInterval(function() {
                if(!isMouseInRect){
                    posx += 10 * dir;
                }
                //clearRect清空画布的一个矩形区域
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                // drawALot();
                //真正要用到复杂的绘画的时候,直接从离屏Canvas上拷贝过来
                ctx.drawImage(offCanvas,0,0,offCanvas.width, offCanvas.height,0,0, canvas.width, canvas.height);
                ctx.fillRect(posx, posy, 50, 50);
                if(posx + 50 >= canvas.width){
                    dir = -1;
                }else if(posx <= 0){
                    dir = 1;
                }
            },100);
    
            drawALot();
        </script>
    </body>
    </html>

    案例:电子名片生成器

    index.html

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8" />
      <title>电子名片生成器</title>
      <link href="style/style.css" rel="stylesheet" />
    </head>
    <body>
      <div class="left-div">
        <div class="line">
          <input id="name" type="text" placeholder="姓名"/>
        </div>
        <div class="line">
          <input id="address" type="text" placeholder="地址"/>
        </div>
        <div class="line">
          <input id="job" type="text" placeholder="职业"/>
        </div>
        <div class="line">
          <input id="slogan" type="text" placeholder="口号" />
        </div>
        <div class="line">
          <button id="generateBtn">生成名片</button>
        </div>
      </div>
      <div class="right-div">
        <canvas id="cardCanvas">
          您的浏览器不支持Canvas,请升级浏览器
        </canvas>
        <canvas id="animCanvas">
          您的浏览器不支持Canvas,请升级浏览器
        </canvas>
      </div>
      <script src="script/main.js"></script>
    </body>
    </html>

    style.css

    * {
      margin: 0;
      padding: 0;
    }
    html, body {
      height: 100%;
    }
    .left-div {
      width: 30%;
      height: 100%;
      float: left;
      background: #a4a296;
    }
    .line {
      text-align: center;
      margin-top: 30px;
    }
    .line:first-child {
      margin-top: 200px;
    }
    .line span {
      color: white;
    }
    .line input {
      width: 300px;
      height: 30px;
      border-radius: 15px;
      padding-left: 15px;
      outline: none;
      border: none;
    }
    .line button {
      width: 100px;
      height: 30px;
      outline: none;
      border: none;
      background: #222;
      color: #DDD;
      cursor: pointer;
      position: relative;
      border-radius: 15px;
    }
    .line button:hover {
      background: #000;
      color: #FFF;
    }
    .line button:active {
      left: 1px;
      top: 1px;
    }
    .right-div {
      width: 70%;
      height: 100%;
      float: left;
      background: #eee9d3;
      text-align: center;
      position: relative;
    }
    .right-div canvas {
      position: absolute;
      top: 200px;
      left: 50%;
      margin-left: -300px;
    }
    #cardCanvas {
      display: none;
    }

    main.js

    // 创建和设置cardCanvas,该canvas作为离屏canvas
    var cardCanvas = document.getElementById('cardCanvas');
    var cardCtx = cardCanvas.getContext('2d');
    cardCtx.canvas.width = 600;
    cardCtx.canvas.height = 100;
    
    // 加载图片
    var img = new Image();
    img.src = "images/logo.png";
    img.onload = function() {
      cardCtx.drawImage(img, 10, 10);
    }
    
    var generateBtn = document.getElementById("generateBtn");
    generateBtn.onclick = function() {
      cardCtx.clearRect(0, 0, cardCtx.canvas.width, cardCtx.canvas.height);
      // 背景的线性渐变
      var linearGradient = cardCtx.createLinearGradient(0, 0, cardCtx.canvas.width, cardCtx.canvas.height);
      linearGradient.addColorStop(0.5, 'rgb(0,0,0)');
      linearGradient.addColorStop(1, 'rgb(133,133,133)');
      cardCtx.fillStyle = linearGradient;
      cardCtx.fillRect(0, 0, cardCtx.canvas.width, cardCtx.canvas.height);
      // logo图像
      cardCtx.drawImage(img, 10, 10);
      // 获取姓名、地址、职业,绘制,并计算长度
      var name = document.getElementById("name").value || "请输入姓名";
      var address = document.getElementById("address").value || "请输入地址";
      var job = document.getElementById("job").value || "请输入职业";
      var nameWidth, addressWidth, jobWidth, maxWidth = 0;
      cardCtx.font = "bold 30px sans-serif";
      cardCtx.fillStyle = "#fff";
      cardCtx.fillText(name, 105, 35);
      nameWidth = cardCtx.measureText(name).width;
      cardCtx.font = "bold 20px sans-serif";
      cardCtx.fillText(address, 105, 60);
      cardCtx.fillText(job, 105, 85);
      addressWidth = cardCtx.measureText(address).width;
      jobWidth = cardCtx.measureText(job).width;
      if(maxWidth < nameWidth) {
        maxWidth = nameWidth;
      }
      if(maxWidth < addressWidth) {
        maxWidth = addressWidth;
      }
      if(maxWidth < jobWidth) {
        maxWidth = jobWidth;
      }
      // 绘制口号
      var slogan = document.getElementById("slogan").value || "请输入口号";
      cardCtx.save();
      // 做图形变换
      cardCtx.rotate(-0.1);
      cardCtx.translate(0, 50);
      // 阴影
      cardCtx.shadowOffsetX = 10;
      cardCtx.shadowOffsetY = 10;
      cardCtx.shadowColor = 'rgba(0, 0, 0, 0.5)';
      cardCtx.shadowBlur = 1.5;
      cardCtx.fillStyle = "#ddd";
      // 计算口号位置
      var solganWidth;
      solganWidth = cardCtx.measureText(slogan).width;
      var offset = (cardCtx.canvas.width - 115 - maxWidth - solganWidth) / 2;
      cardCtx.fillText(slogan, 115 + maxWidth + offset, 50);
      // 画曲线
      cardCtx.beginPath();
      cardCtx.moveTo(115 + maxWidth + offset, 70);
      cardCtx.quadraticCurveTo(115 + maxWidth + offset, 50, 115 + solganWidth + maxWidth + offset, 60);
      cardCtx.strokeStyle = "#ddd";
      cardCtx.stroke();
      cardCtx.restore();
    }
    // 触发click事件
    generateBtn.click();
    
    // 创建和设置animCanvas,该canvas才是真正的显示
    var animCanvas = document.getElementById('animCanvas');
    var animCtx = animCanvas.getContext('2d');
    animCtx.canvas.width = 600;
    animCtx.canvas.height = 100;
    
    var circles = [];
    setInterval(function() {
      // 擦出画布
      animCtx.clearRect(0, 0, animCtx.canvas.width, animCtx.canvas.height);
      // 把离屏canvas的内容画进来
      animCtx.drawImage(cardCanvas, 0, 0, animCtx.canvas.width, animCtx.canvas.height,
        0, 0, cardCtx.canvas.width, cardCtx.canvas.height);
      // 绘制下落的圆形
      for(var i=0; i<=10; i++) {
        if(!circles[i]) {
          circles[i] = {};
          circles[i].radius = Math.floor(Math.random() * 5) + 1;
          circles[i].y = - circles[i].radius - Math.floor(Math.random() * 10);
          circles[i].x = i * 60 + Math.floor(Math.random() * 10) - 5;
          circles[i].vy = Math.floor(Math.random() * 5) + 1;
        }
        animCtx.beginPath();
        animCtx.arc(circles[i].x, circles[i].y, circles[i].radius, 0, Math.PI * 2);
        animCtx.fillStyle = "rgba(255, 255, 255, 0.5)";
        animCtx.fill();
        circles[i].y = circles[i].y + circles[i].vy;
        if(circles[i].y > animCtx.canvas.height + circles[i].radius * 2) {
          circles[i] = undefined;
        }
      }
    }, 100);

    案例:山中明月风景图

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
        <style>
            canvas{background-color:#000;opacity:0.7}
        </style>
    </head>
    <body>
        <canvas id="canvas" width="720px" height="600px">您的浏览器不支持canvas</canvas>
        <script>
            var canvas=document.getElementById("canvas");
            var context=canvas.getContext("2d");
    
            // 月亮绘制
            context.shadowOffsetX=10;
            context.shadowOffsetY=10;
            context.shadowBlur=5;
            context.shadowColor='rgba(255,255,255,0.2)';
            context.fillStyle='yellow';
            context.arc(100,100,40,0,Math.PI*2,true);
            context.fill();
    
            // 文字绘制
            context.beginPath();
            var str='山高月小';
            context.font='50px 宋体';
            context.fillStyle='#fff';
            context.shadowColor='rgba(255,255,255,0.4)';
            context.fillText(str,400,200);
    
            // 山峰绘制
            context.beginPath();
            context.lineWidth=5;
            context.strokeStyle='lightblue';
            context.moveTo(14, 600);
            context.quadraticCurveTo(60, 193, 123, 600);
            context.stroke();
    
            context.beginPath();
            context.moveTo(298, 600);
            context.bezierCurveTo(81, 193, 73, 691, 100, 600);
            context.stroke();
    
            context.beginPath();
            context.moveTo(500, 600);
            context.bezierCurveTo(451, 34, 273, 361, 298, 600);
            context.stroke();
    
            context.beginPath();
            context.moveTo(452, 600);
            context.bezierCurveTo(569, 210, 695, 426, 715, 600);
            context.stroke();
    
        </script>
    </body>
    </html>
  • 相关阅读:
    vue+filesaver+xlsx导出table为excel
    layer弹窗第一次不居中。然后再点击就居中了。解决办法
    GitHub的Fork 是什么意思
    什么时候会发送options请求
    实现H5连接分享给好友或朋友圈自定义分享内容(标题、图片、简介)的方法代码
    vue的element的table表头自定义添加按钮
    小程序配置体验版添加参数
    迅为iMX8M Mini开发板硬件接口原理分析
    迅为i.MX8MM 核心板引脚说明(按功能划分)
    迅为3399开发板Ubuntu 系统双屏异显,双屏同显测试
  • 原文地址:https://www.cnblogs.com/chenyingying0/p/12157008.html
Copyright © 2020-2023  润新知