canvas 订阅
《canvas》是从2005年10月3日开始放映的24集日本动画,由F&C ZEXCS制作发行,讲述了拥有超人的绘画天分的男主角的故事。 展开全文
《canvas》是从2005年10月3日开始放映的24集日本动画,由F&C ZEXCS制作发行,讲述了拥有超人的绘画天分的男主角的故事。
信息
外文名
Canvas
制作·发行
F&C ZEXCS
放映日期
2005年10月3日
日文名
虹色のスケッチ
国    家
日本
总共集数
24
canvas剧情简介
拥有超人的绘画天分的男主角,却因某事故无法再次执起画笔,只能委身于某所大学,担任美术课的顾问。受男主角指导走向绘画之路的女主角,却因目睹双亲车祸身亡的现场,而在作画中无法使用红色。青梅竹马的女伴,可是高中时代的告白,却遭到男主角的拒绝,现在她又重新闯入了男主角的生活。 偶然的再会…… 三人之间,会发生什么?爱的前路,会走向哪里?
收起全文
精华内容
下载资源
问答
  • canvas

    千次阅读 多人点赞 2018-04-17 15:29:27
    canvas画布的左上角为笛卡尔坐标系的原点,且y轴的正方向向下,x轴的正方向向右 二、准备工作:布置画布、获取画布、获取画笔 <canvas id=“canvas”></canvas> var canvas = document....

    一、规则

    以canvas画布的左上角为笛卡尔坐标系的原点,且y轴的正方向向下,x轴的正方向向右

    二、准备工作:布置画布、获取画布、获取画笔

    <canvas id=“canvas”></canvas>
    var canvas = document.getElementById("canvas")
    var context = canvas.getContext("2d")

    三、分类

    3、1:线条

    移动画笔:context.moveTo(100,100),画笔起点

    画笔停点:context.linrTo(600,600),画笔终点

    画笔粗细的配置:context.lineWidth='5'

    画笔颜色的配置:context.strokeStyle="#353537"

    绘制类型:fill()填充  、stroke()描边

    beginpath()开始绘制,可以使后面的线段的颜色等不覆盖前面的,结束绘制为fill()、stroke()、closePath()

    	var canvas = document.getElementById('canvas');
            var context = canvas.getContext('2d');
            context.beginPath();
            context.moveTo(20,20);
            context.lineTo(30,30);
            context.lineTo(20,40);
            context.lineTo(20,20);
            context.closePath();//不使用closePath结束绘制,左上角的会有缺口,用closePath的时候可以不用进行结尾,即最后一笔可以不画
            context.lineWidth = '2'; //线条粗细
            context.strokeStyle = '	#228B22';//线条颜色
            context.fillStyle = "yellow";//内容填充色
            context.stroke();//描边结束
            context.fill(); //绘制结束
    3、2:矩形,结合上面的知识点,矩形直接上例子就可以了
         window.onload = function(){
                var canvas = document.getElementById("canvas");
                var context = canvas.getContext("2d");
    
                rectfun(context,80,80,100,100,2,'black','white');
                rectfun(context,85,85,90,90,2,'black','white');
                rectfun(context,87,87,85,85,1,'black','white');
                rectfun(context,90,90,80,80,2,'black','white');
                rectfun(context,100,100,60,60,2,'black','white');
                rectfun(context,110,110,40,40,2,'black','white');
                rectfun(context,120,120,20,20,2,'black','white');
                rectfun(context,130,130,1,1,2,'black','white');
         }
       function rectfun(cxt,x,y,width,height,borderwidth,bordercolor,fillcolor){
                cxt.beginPath();
                cxt.rect(x,y,width,height);//生成矩形
                // cxt.closePath() 使用rect的时候,closePath可以不用
                cxt.lineWidth = borderwidth;//宽度
                cxt.strokeStyle = bordercolor;//颜色
                cxt.fillStyle = fillcolor;//填充色
                cxt.stroke();
                cxt.fill();
         }矩形效果图如下:

    
     

    3、3:线条属性,共有4个属性

          3.3.1、lineCap属性(线条的帽子):定义线的终点属性,有3个属性值(这些属性只会在终点起作用,折线处不会起作用)

    * butt:默认值,端点是垂直于线段边缘的平直边缘。
    * round:端点是在线段边缘处以线宽为直径的半圆。
    * square:端点是在选段边缘处以线宽为长、以一半线宽为宽的矩形。

        例子:

        window.onload = function(){
            var canvas = document.getElementById("canvas");
            canvas.width = 800;
            canvas.height = 600;
            var context = canvas.getContext("2d");
    
            context.lineWidth = 50;
            context.strokeStyle = "#1BAAAA";
    
            context.beginPath();
            context.moveTo(100,100);
            context.lineTo(700,100);
            context.lineCap = "butt";
            context.stroke();
    
            context.beginPath();
            context.moveTo(100,300);
            context.lineTo(700,300);
            context.lineCap = "round";
            context.stroke();
    
            context.beginPath();
            context.moveTo(100,500);
            context.lineTo(700,500);
            context.lineCap = "square";
            context.stroke();
    
            //下面画两个基准线方便观察
            context.lineWidth = 3;
            context.strokeStyle = "black";
    
            context.beginPath();
            context.moveTo(100,0);
            context.lineTo(100,600);
            context.moveTo(700,0);
            context.lineTo(700,600);
            context.stroke();
        }

        效果:

        3.3.2、lineJoin(线条的连接),定义折线处的属性,直接看代码和效果就可以明白

        代码:

    window.onload = function(){
            var canvas = document.getElementById("canvas");
            canvas.width = 800;
            canvas.height = 600;
            var context = canvas.getContext("2d");
    
            context.beginPath();
            context.moveTo(100,100);
            context.lineTo(300,300);
            context.lineTo(100,500);
            context.lineJoin = "miter";
            context.lineWidth = 20;
            context.strokeStyle = "red";
            context.stroke();
    
            context.beginPath();
            context.moveTo(300,100);
            context.lineTo(500,300);
            context.lineTo(300,500);
            context.lineJoin = "bevel";
            context.lineWidth = 20;
            context.strokeStyle = "blue";
            context.stroke();
    
            context.beginPath();
            context.moveTo(500,100);
            context.lineTo(700,300);
            context.lineTo(500,500);
            context.lineJoin = "round";
            context.lineWidth = 20;
            context.strokeStyle = "black";
            context.stroke();
        }

        效果:

        

            3.3.3、当lineJoin设置为miter时(默认),此时可以使用miterLimit属性(不常用)

            例子:

            

    window.onload = function(){
            var canvas = document.getElementById("canvas");
            canvas.width = 800;
            canvas.height = 600;
            var context = canvas.getContext("2d");
    
            context.beginPath();
            context.moveTo(100,100);
            context.lineTo(300,300);
            context.lineTo(100,500);
            context.lineJoin = "miter";
            context.miterLimit = 10;
            context.lineWidth = 5;
            context.strokeStyle = "red";
            context.stroke();
    
            context.beginPath();
            context.moveTo(300,200);
            context.lineTo(500,300);
            context.lineTo(300,400);
            context.lineJoin = "miter";
            context.miterLimit = 10;
            context.lineWidth = 5;
            context.strokeStyle = "blue";
            context.stroke();
    
            context.beginPath();
            context.moveTo(500,290);
            context.lineTo(700,300);
            context.lineTo(500,310);
            context.lineJoin = "miter";
            context.miterLimit = 10;
            context.lineWidth = 5;
            context.strokeStyle = "black";
            context.stroke();
        }

    效果:原理链接:http://7xkcl8.com1.z0.glb.clouddn.com/edu6-4.png

    3、4填充颜色

        3.4.1填充基本颜色

        (1)颜色字符串填充

    context.fillStyle = "red";

        (2)十六进制字符串

    context.fillStyle = "#FF0000";

        (3)rgb

    context.fillStyle = "rgba(255,0,0,1)";

        (4)hsl()

    context.fillStyle = "hsl(0,100%,50%)";

        (5)hsla()

    context.fillStyle = "hsla(0,100%,50%,1)";

    3、5填充渐变形状,线性和径向

        3.5.1线性渐变

            例子:

    var canvas = document.getElementById("canvas");
            canvas.width = 800;
            canvas.height = 600;
            var context = canvas.getContext("2d");
    
            context.rect(200,100,400,400);//x起始坐标  y起始坐标  宽  高 
    
            //添加渐变线
            var grd = context.createLinearGradient(200,300,600,300);  //xstart,ystart,xend,yend 从(200,300)到(600,300)的径向
    
            //添加颜色断点
            grd.addColorStop(0,"black");
            grd.addColorStop(0.5,"white");  
            grd.addColorStop(1,"black");
    
            //应用渐变
            context.fillStyle = grd;
    
            context.fill();

            效果:

            

            3.5.2绘制矩形的快捷方式

    `fillRect(x,y,width,height)`、`stroke(x,y,width,height)`。这两个函数可以分别看做`rect()`与`fill()`以及`rect()`与`stroke()`的组合。因为`rect()`仅仅只是规划路径而已,而这两个方法确实实实在在的绘制。

        例子,直接看例子就可以直接看明白:

    window.onload = function(){
            var canvas = document.getElementById("canvas");
            canvas.width = 800;
            canvas.height = 600;
            var context = canvas.getContext("2d");
            //添加渐变线
            var grd = context.createLinearGradient(100,300,700,300);xstart,ystart,xend,yend 从(100,300)到(700,300)的径向
            //添加颜色断点
            grd.addColorStop(0,"olive");
            grd.addColorStop(0.5,"aqua");
            grd.addColorStop(0.75,"fuchsia");
            grd.addColorStop(0.25,"teal");
            //应用渐变
            context.fillStyle = grd;
            context.strokeStyle = grd;
    
            context.strokeRect(200,150,450,50);
    
            context.fillRect(200,300,300,50);
        }

        效果:

        3、6:填充样式,createPattern()填充图案,需要传递两个参数createPattern(img,repeat-style),第一个对象是img实例,第二个对象是string类型,有4种填充类型,repeat,repeat-x,repeat-y,no-repeat,第一种参数还可以传入一个canvas或者是video对象,这里只说img对象,其余的自己尝试

    window.onload = function(){
            var canvas = document.getElementById("canvas");
            canvas.width = 800;
            canvas.height = 600;
            var context = canvas.getContext("2d");
    
            var img = new Image();//创建img对象
            img.src = "1.jpg";//为img对象指定图片源
            img.onload = function(){
                var pattern = context.createPattern(img, "repeat");//指定类型
                context.fillStyle = pattern;//纹理填充
                context.fillRect(0,0,800,600);//快速制作矩形的方法,xstart,ystrart,width,height
       }

        效果图:(代码里面img使用onload,是对图片进行预加载,)

        3、7:绘制标准圆弧arc()函数

            arc(x,y,r,startAngle,endAngle,anticlockwise)

            x,y圆心坐标,r半径,   

            startAngle:开始的弧度值,endAngle:结束的弧度值

            anticlockwise:表示绘制的方法(用布尔值进行表示),是(false)顺时针还是(true)逆时针,当此值不填写的时候,默认为false,顺时针,弧度值得规则如图:

            

        例子:(我画的准备图的是随便在浏览器的页面上画的,请自动忽略无用的背景)

            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            context.fillStyle = "#FFF";
            context.fillRect(0,0,800,600);
    
            context.beginPath();
            context.arc(150,250,50,Math.PI, Math.PI * 3 / 2);
            context.lineTo(250,200);
            context.arc(250,250,50,Math.PI* 3 / 2, Math.PI *2);
            context.lineTo(300,400);
            context.arc(250,400,50,0, Math.PI*1/2);
            context.lineTo(150,450);
            context.arc(150,400,50,Math.PI*1/2, Math.PI);
            // context.lineTo(100,250);
            context.closePath();
            context.strokeStyle = "#0078AA";
            context.stroke();

        (准备图)

    (效果图)

    3、8:切点绘制圆弧arcTo()

    。。。

    展开全文
  • 本人也是前端小白,正在努力学习的路上奔跑~最近看到一位博主大大的绘制星空博文,加上最近对面向对象编程思想的理解,也照葫芦画瓢复现了一个demo,顺便熟悉一下canvas的一些API。 源代码 <!DOCTYPE html> &...

    本人也是前端小白,正在努力学习的路上奔跑~最近看到一位博主大大的绘制星空博文,加上最近对面向对象编程思想的理解,也照葫芦画瓢复现了一个demo,顺便熟悉一下canvas的一些API。

    源代码

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>StarSky</title>
      </head>
      <body></body>
      <style>
        * {
          margin: 0;
          padding: 0;
          width: 100vw;
          height: 100vh;
          overflow: hidden;
        }
      </style>
      <script>
        /**
         *  © WindyZ write in 2020
         *  进度表
         *  1125 完成初始化方法以及相关参数
         *       完成绘制背景,以及窗口大小改变的监听
         *  1126 完成月亮绘制,修复窗口大小监听无效的问题
         *  1127 完成星星绘制,未解决月亮周围减少星星问题
         *  1201 完成流星绘制,抽象出 Star 和 Commet 类
         *  1211 完成山体绘制,完成大体的动画
         */
    
        // 星星类
        class Star {
          x = 0; // x 坐标
          y = 0; // y 坐标
          opacity = 0; // 星星透明度
          radius = 0; // 星星半径
          is_weak = true; // 星星闪烁的时候,透明度是否先减小到0,再增加到1
    
          constructor(width, height, moon_radius) {
            this.init(width, height, moon_radius);
          }
    
          init(w, h, m_r) {
            this.x = Math.random() * w;
            this.y = Math.random() * h * 0.8;
    
            this.x >= w / 9 - m_r && this.x <= w / 9 + m_r * 3
              ? (this.x = this.x + (Math.random() >= 0.5 ? -m_r * 2 : m_r * 2))
              : "";
    
            this.y >= h / 9 - m_r && this.y <= h / 9 + m_r * 3
              ? (this.y = this.y + (Math.random() >= 0.5 ? -m_r * 2 : m_r * 2))
              : "";
    
            this.opacity = Math.random() * 1.1;
            this.radius = Math.random() * 0.8 + 0.5;
          }
    
          // 获得参数
          get getStarVal() {
            return {
              x: this.x,
              y: this.y,
              opacity: this.opacity,
              radius: this.radius,
              is_weak: this.is_weak,
            };
          }
    
          // 更改参数
          setStarVal(val) {
            if (!!val) {
              for (let key in val) {
                if (key == "x") {
                  this.x = val[key];
                }
                if (key == "y") {
                  this.y = val[key];
                }
                if (key == "opacity") {
                  this.opacity = val[key];
                }
                if (key == "radius") {
                  this.radius = val[key];
                }
                if (key == "is_weak") {
                  this.is_weak = val[key];
                }
              }
            }
          }
        }
    
        // 流星类
        class Commet {
          x = 0; // 流星 x 坐标
          y = 0; // 流星 y 坐标
          radius = 0; // 流星半径
          opacity = 0; // 流星透明度
          tail_length = 0; // 流星尾巴长度
          tail_direct = 0; // 流星的方向,暂时未做开发
          ori_speed = 0; // 流星的初始速度
          velocity = 0; // 流星的加速度,一般来说是个负数,使速度递减
    
          constructor(width, height) {
            this.init(width, height);
          }
    
          // 初始化流星参数
          init(w, h) {
            this.x = Math.random() * w;
            this.y = Math.random() * h * 0.8;
            this.radius = Math.random() * 0.5 + 0.5;
            this.opacity = Math.random() * 0.7 + 0.4;
            this.tail_length = Math.random() * 15 + 25;
            this.ori_speed = Math.random() * 0.5 + 2;
            this.velocity = -(Math.random() * 0.005 + 0.005);
          }
    
          // 更改参数
          setCommetVal(val) {
            if (!!val) {
              for (let key in val) {
                if (key == "x") {
                  this.x = val[key];
                }
                if (key == "y") {
                  this.y = val[key];
                }
                if (key == "radius") {
                  this.radius = val[key];
                }
                if (key == "opacity") {
                  this.opacity = val[key];
                }
                if (key == "tail_length") {
                  this.tail_length = val[key];
                }
                if (key == "tail_direct") {
                  this.tail_direct = val[key];
                }
                if (key == "ori_speed") {
                  this.ori_speed = val[key];
                }
              }
            }
          }
    
          // 获取参数
          get getCommetVal() {
            return {
              x: this.x,
              y: this.y,
              radius: this.radius,
              opacity: this.opacity,
              tail_length: this.tail_length,
              ori_speed: this.ori_speed,
              velocity: this.velocity,
            };
          }
        }
    
        // 绘制整个画布的类
        class DrawSky {
          constructor() {
            this.width; // 画布宽度
            this.height; // 画布高度
    
            // 使用双缓冲绘图技术,增强绘制过程的流畅度
            // 这是页面真实渲染画布
            this.realCanvas = document.createElement("canvas");
            document.body.appendChild(this.realCanvas);
            this.realCtx = this.realCanvas.getContext("2d");
    
            // 这是缓冲绘制画布
            this.canvas = document.createElement("canvas");
            this.ctx = this.canvas.getContext("2d");
    
            this.moon_radius; // 月亮半径
            this.star_arr = []; // 存放星星数组
            this.commet_arr = []; // 存放流行数组
            this.mountain_arr = []; // 存放山的数组
            this.timer = null;
    
            this.init(); // 调用初始化方法
    
            // 添加窗口大小改变监听事件
            window.addEventListener("resize", () => {
              if (timer) {
                window.cancelAnimationFrame(timer);
                timer = null;
              }
              this.cleanCanvas();
              this.init();
            });
          }
    
          // 初始化方法画布数据
          init() {
            this.width = window.innerWidth
              ? window.innerWidth
              : document.body.clientWidth;
            this.height = window.innerHeight
              ? window.innerHeight
              : document.body.clientHeight;
    
            this.moon_radius = 50;
    
            this.canvas.width = this.width;
            this.canvas.height = this.height;
            this.realCanvas.width = this.width;
            this.realCanvas.height = this.height;
    
            // 执行绘画控制方法
            this.drawControl();
          }
    
          // 第一次开始绘制动画
          drawControl() {
            this.drawSkyBackground();
            this.drawMoon();
            this.drawStar();
            this.drawCommet();
            this.drawMountain();
            // 实现双缓冲
            this.realCtx.drawImage(this.canvas, 0, 0, this.width, this.height);
            this.cleanCanvas();
            this.startAnimate();
          }
    
          // 循环绘制动画
          startAnimate() {
            // 这是第一种通过 setInterval 控制绘画方法
            // if (this.interval) {
            //     clearInterval(this.interval)
            // }
            // this.interval = setInterval(() => {
            //     this.cleanCanvas()
            //     this.drawSkyBackground()
            //     this.drawMoon()
            //     this.drawStar()
            //     this.drawCommet()
            //     this.drawMountain()
            // }, 20)
    
            // 这是第二种通过 requestAnimationFrame 控制绘画方法
            this.drawSkyBackground();
            this.drawMoon();
            this.drawStar();
            this.drawCommet();
            this.drawMountain();
            // 将备用画布画好的图片,绘制到页面真正渲染的画布上
            this.realCtx.drawImage(this.canvas, 0, 0, this.width, this.height);
            this.cleanCanvas();
            this.timer = window.requestAnimationFrame(() => this.startAnimate());
          }
    
          // 绘制背景
          drawSkyBackground() {
            // 这种是从上到下的渐变背景
            // let gradientColor = this.ctx.createLinearGradient(0, 0, 0, this.height);
            // gradientColor.addColorStop(0, "#000211");
            // gradientColor.addColorStop(0.3, "#080d23");
            // gradientColor.addColorStop(0.7, "#18203d");
            // gradientColor.addColorStop(1, "#293756");
            // this.ctx.fillStyle = gradientColor;
            // this.ctx.fillRect(0, 0, this.width, this.height);
    
            // 这种是中间向四周发散光芒的背景
            let radialColor = this.ctx.createRadialGradient(
              this.width / 2,
              this.height * 1.5,
              this.width / 8,
              this.width / 2,
              this.height * 0.9,
              this.width * 2
            );
            radialColor.addColorStop(0, "#293756");
            radialColor.addColorStop(0.5, "rgba(0, 0, 0, 0)");
            this.ctx.fillStyle = radialColor;
            this.ctx.fillRect(0, 0, this.width, this.height);
          }
    
          // 绘制月亮
          drawMoon() {
            let moonRadial = this.ctx.createRadialGradient(
              this.width / 9 + this.moon_radius,
              this.width / 9 + this.moon_radius,
              this.moon_radius * 0.5,
              this.width / 9 + this.moon_radius,
              this.width / 9 + this.moon_radius,
              this.moon_radius
            );
            moonRadial.addColorStop(0, "rgba(255, 255, 255, 1)");
            moonRadial.addColorStop(0.6, "rgba(255, 255, 255, 1)");
            moonRadial.addColorStop(1, "rgba(255, 255, 255, 0)");
            this.ctx.fillStyle = moonRadial;
            this.ctx.fillRect(
              this.width / 9,
              this.width / 9,
              this.moon_radius * 2,
              this.moon_radius * 2
            );
          }
    
          // 实例化山的参数
          drawMountain() {
            // 初始化山的数据
            if (!this.mountain_arr || this.mountain_arr.length === 0) {
              let mountain_obj = {};
    
              // 定义起始点坐标
              // x 的范围为 [0, this.width], x 方向每次递增的值范围为 [100, 200)
              // y 的范围为 [50, 70)
              let start_x = 0;
              let start_y = this.height - (Math.random() * 20 + 60);
    
              // 记录一下最原始的坐标
              let ori_x = start_x;
              let ori_y = start_y;
    
              mountain_obj.x = start_x;
              mountain_obj.y = start_y;
              this.mountain_arr.push(mountain_obj);
    
              while (start_x < this.width) {
                mountain_obj = {};
    
                // 生成下一个点的坐标
                let end_x = Math.random() * 20 + 20 + start_x;
                let end_y = this.height - (Math.random() * 20 + 60);
                if (end_x >= this.width) {
                  end_x = this.width;
                }
    
                // 决定本次绘画用直线还是二次贝塞尔曲线
                // 0 直线
                // 1 二次贝塞尔
                let draw_mode = Math.random() >= 0.5 ? 0 : 1;
                let control_x = 0;
                let control_y = 0;
                if (draw_mode === 1) {
                  // 生成控制点坐标
                  // x 轴控制点在 start_x 和 end_x 之间
                  // y 轴控制点在 [50, 100)
                  control_x = Math.random() * (end_x - start_x) + start_x;
                  control_y =
                    Math.random() >= 0.5
                      ? Math.min(end_y, start_y) - Math.random() * 20
                      : Math.max(end_y, start_y) + Math.random() * 50;
                }
    
                start_x = end_x;
                start_y = end_y;
    
                mountain_obj.draw_mode = draw_mode;
                mountain_obj.x = end_x;
                mountain_obj.y = end_y;
                mountain_obj.control_x = control_x;
                mountain_obj.control_y = control_y;
                this.mountain_arr.push(mountain_obj);
              }
            }
    
            this.drawMountainPic(this.mountain_arr);
          }
    
          // 根据山的数据进行绘制山
          drawMountainPic(mountain_arr) {
            this.ctx.beginPath();
            this.ctx.lineTo(mountain_arr[0].x, mountain_arr[0].y);
    
            for (let i = 1; i < mountain_arr.length; i++) {
              if (mountain_arr[i].draw_mode === 0) {
                this.ctx.lineTo(mountain_arr[i].x, mountain_arr[i].y);
              } else {
                this.ctx.quadraticCurveTo(
                  mountain_arr[i].control_x,
                  mountain_arr[i].control_y,
                  mountain_arr[i].x,
                  mountain_arr[i].y
                );
              }
            }
    
            this.ctx.lineTo(this.width, this.height);
            this.ctx.lineTo(0, this.height);
            this.ctx.lineTo(mountain_arr[0].x, mountain_arr[0].y);
    
            this.ctx.fillStyle = "#000";
            this.ctx.fill();
    
            this.ctx.closePath();
          }
    
          // 实例化流星参数
          drawCommet() {
            // 第一次绘制流星
            if (!this.commet_arr || this.commet_arr.length === 0) {
              let commetNum = Math.random() * 10 + 5;
              this.commet_arr = [];
              for (let i = 0; i < commetNum; i++) {
                // 创建流星实例对象
                let commet = new Commet(this.width, this.height);
                let commet_obj = commet.getCommetVal;
                this.commet_arr.push(commet);
    
                // 绘制流星
                this.drawCommetPic(commet_obj);
              }
            }
    
            // 更改流星位置,实现流星动画
            else {
              for (let i = 0; i < this.commet_arr.length; i++) {
                let commet_obj = this.commet_arr[i].getCommetVal;
    
                commet_obj.ori_speed =
                  commet_obj.ori_speed + commet_obj.velocity > 1
                    ? commet_obj.ori_speed + commet_obj.velocity
                    : 1;
                commet_obj.x -= commet_obj.ori_speed / Math.sqrt(2);
                commet_obj.y += commet_obj.ori_speed / Math.sqrt(2);
                commet_obj.opacity =
                  commet_obj.opacity - 0.01 > 0 ? commet_obj.opacity - 0.01 : 0;
    
                if (commet_obj.opacity === 0 || commet_obj.speed <= 0) {
                  // 销毁当前流星对象,并新建一个
                  commet_obj = null;
                  this.commet_arr[i] = null;
                  this.commet_arr[i] = new Commet(this.width, this.height);
                  commet_obj = this.commet_arr[i].getCommetVal;
                }
    
                // 绘制流星
                this.drawCommetPic(commet_obj);
    
                this.commet_arr[i].setCommetVal(commet_obj);
              }
            }
          }
    
          // 根据流星的数据进行绘制流星
          drawCommetPic(commet_obj) {
            // 画圆形主体
            this.ctx.beginPath();
            this.ctx.fillStyle = `rgba(255, 255, 255, ${commet_obj.opacity})`;
            this.ctx.arc(
              commet_obj.x,
              commet_obj.y,
              commet_obj.radius,
              0,
              2 * Math.PI
            );
            this.ctx.fill();
            this.ctx.closePath();
    
            // 画尾巴
            this.ctx.beginPath();
            let tailColor = this.ctx.createLinearGradient(
              commet_obj.x,
              commet_obj.y,
              commet_obj.x +
                Math.sin((45 * Math.PI) / 180) * commet_obj.tail_length,
              commet_obj.y - Math.sin((45 * Math.PI) / 180) * commet_obj.tail_length
            );
            tailColor.addColorStop(0, `rgba(255, 255, 255, ${commet_obj.opacity})`);
            tailColor.addColorStop(1, "rgba(255, 255, 255, 0)");
            this.ctx.fillStyle = tailColor;
            this.ctx.strokeStyle = tailColor;
            this.ctx.lineWidth = commet_obj.radius * 2;
            this.ctx.moveTo(commet_obj.x, commet_obj.y);
            this.ctx.lineTo(
              commet_obj.x +
                Math.sin((45 * Math.PI) / 180) * commet_obj.tail_length,
              commet_obj.y - Math.sin((45 * Math.PI) / 180) * commet_obj.tail_length
            );
            this.ctx.fill();
            this.ctx.stroke();
            this.ctx.closePath();
          }
    
          // 实例化星星参数
          drawStar() {
            // 初始化星星数组
            if (!this.star_arr || this.star_arr.length === 0) {
              let star_num = Math.random() * 100 + 50;
              this.star_arr = [];
    
              for (let i = 0; i < star_num; i++) {
                let star = new Star(this.width, this.height, this.moon_radius);
                let star_obj = star.getStarVal;
    
                this.star_arr.push(star);
    
                this.drawStarPic(star_obj);
              }
            }
    
            // 更改星星透明度,实现星星渐隐动画
            // 根据窗口中心点,计算星星旋转坐标,实现星移
            else {
              for (let i = 0; i < this.star_arr.length; i++) {
                let star_obj = this.star_arr[i].getStarVal;
                if (star_obj.is_weak) {
                  // 降低透明度
                  star_obj.opacity =
                    star_obj.opacity - 0.01 > 0 ? star_obj.opacity - 0.01 : 0;
                  if (star_obj.opacity <= 0) {
                    star_obj.is_weak = false;
                  }
                } else {
                  // 提高透明度
                  star_obj.opacity =
                    star_obj.opacity + 0.01 < 1 ? star_obj.opacity + 0.01 : 1;
                  if (star_obj.opacity >= 1) {
                    star_obj.is_weak = true;
                  }
                }
    
                // 转换原点坐标为左下角,得到新的星星坐标点以及中心点
                let star_x = star_obj.x,
                  star_y = this.height - star_obj.y,
                  c_x = this.width / 2,
                  c_y = this.height / 2;
                // 计算当前星星坐标和中心点的距离
                let r = Math.sqrt(
                  Math.pow(star_x - c_x, 2) + Math.pow(star_y - c_y, 2)
                );
                // 计算当前星星坐标相对中心点的角度
                let angle =
                  (Math.atan2(star_y - c_y, star_x - c_x) * 180) / Math.PI;
                angle = angle + 0.1 <= 360 ? angle + 0.1 : 0;
                let x = c_x + Math.sin((angle * Math.PI) / 180) * r;
                let y = c_y - Math.cos((angle * Math.PI) / 180) * r;
                // 将新的星星坐标转换为原来的坐标系坐标
                star_obj.x = x;
                star_obj.y = this.height - y;
    
                this.star_arr[i].setStarVal(star_obj);
                this.drawStarPic(star_obj);
              }
            }
          }
    
          // 根据星星的数据进行绘制星星
          drawStarPic(star_obj) {
            this.ctx.beginPath();
            this.ctx.fillStyle = `rgba(255, 255, 255, ${star_obj.opacity})`;
            this.ctx.arc(star_obj.x, star_obj.y, star_obj.radius, 0, 2 * Math.PI);
            this.ctx.fill();
            this.ctx.closePath();
          }
    
          // 清空画布
          cleanCanvas() {
            this.ctx.clearRect(0, 0, this.width, this.height);
          }
    
          // 暂停绘画函数,可用于观察绘制过程
          sleep() {
            return new Promise((resolve, reject) => {
              setTimeout(() => {
                resolve();
              }, 1000);
            });
          }
        }
    
        // 新建绘制类的实例对象,开始绘制
        new DrawSky();
      </script>
    </html>
    

    源代码 git 仓库地址

    效果预览地址
    代码中还存在星星绘制过程画面闪烁的问题,暂未找到原因,欢迎大家批评指正啦~

    展开全文
  • js实现截图并保存图片(html转canvascanvas转image)

    万次阅读 热门讨论 2018-07-23 15:16:43
    js实现截图并保存图片在本地(html转canvascanvas转image) 一、html转canvas 需要的库html2canvas.js和canvas2image.js 话不多说,直接上代码! html &amp;amp;amp;amp;lt;h2&amp;amp;amp;amp...

    js实现截图并保存图片在本地(html转canvas、canvas转image)

    简介

    JavaScript实现网页截图,使用的库有两个:

    Html2Canvas.js
    Canvas2Image.js

    我主要是做了两个demo和一个npm包:

    1. 简单版的实现
    2. Webpack+Vue+Element版的实现
    3. js-screenshot-for-npm

    1. 如何使用简单版

    直接打开index.html即可

    2. 如何使用Webpack+Vue+Element版

    # 安装依赖
    npm install
    
    # 在localhost:8080进行热重新加载
    npm run dev
    
    # 压缩构建为生产环境代码
    npm run build
    
    # 构建为生产环境代码并查看捆绑分析器报告
    npm run build --report
    

    使用示例

    原始html是这样的:

    在这里插入图片描述

    这是元素节点:

    在这里插入图片描述

    这是转成canvas之后:

    在这里插入图片描述

    这是元素节点:

    在这里插入图片描述

    这是转成img之后:

    在这里插入图片描述

    这是元素节点:

    在这里插入图片描述

    这是最终截图结果:

    在这里插入图片描述

    3. 使用npm安装js_screen_shots

    npm install --save js_screen_shots
    

    详情见README.md

    展开全文
  • 1.新建canvas.js // 炫酷渐变色背景粒子线条折线连接canvas动画 export const canvas = (val) => { var requestAnimationFrame = window.requestAnimationFrame || function (callback) { window....

    博客地址:http://www.globm.top/blog/1/detail/34
    效果图:
    在这里插入图片描述
    1.新建canvas.js

    
    // 炫酷渐变色背景粒子线条折线连接canvas动画
    export const canvas = (val) => {
      var requestAnimationFrame = window.requestAnimationFrame || function (callback) {
        window.setTimeout(callback, 1000 / 60)
      }
    
      // var canvas = document.getElementsByTagName("canvas")[0];
      let canvas = val
      let ctx = canvas.getContext('2d')
      let maximumPossibleDistance
      let mousePositionX
      let mousePositionY
      let mouseElement
      let lines = 0
      let objects = []
      var initAnimation = function () {
        canvas.width = window.innerWidth
        canvas.height = window.innerHeight
        maximumPossibleDistance = Math.round(Math.sqrt((canvas.width * canvas.width) + (canvas.height * canvas.height)))
        Math.floor(canvas.width / 2)
        Math.floor(canvas.height / 2)
        objects.length = 0
        clearCanvas()
        createParticles()
      }
      window.addEventListener('resize', function () { initAnimation() }, false)
      // 线条参数配置
      var options = {
        // 初始线条数量
        particlesNumber: 80,
        // 圆点大小
        initialSize: 3,
        moveLimit: 50,
        durationMin: 50,
        durationMax: 300,
        drawConnections: true,
        mouseInteractionDistance: 150,
        mouseGravity: true,
        drawMouseConnections: true,
        // 图标色彩
        red: 25,
        green: 200,
        blue: 255,
        opacity: 1,
        // 已连接线条
        connectionRed: 255,
        connectionGreen: 255,
        connectionBlue: 255,
        connectionOpacity: 0.2,
        // 鼠标移动线条
        mouseConnectionRed: 255,
        mouseConnectionGreen: 255,
        mouseConnectionBlue: 255,
        mouseConnectionOpacity: 0.2
    
      }
      var getRandomBetween = function (a, b) {
        return Math.floor(Math.random() * b) + a
      }
      var getDistance = function (element1, element2) {
        var difX = Math.round(Math.abs(element1.positionX - element2.positionX))
        var difY = Math.round(Math.abs(element1.positionY - element2.positionY))
    
        return Math.round(Math.sqrt((difX * difX) + (difY * difY)))
      }
      function Particle (positionX, positionY, size, red, green, blue, opacity) {
        this.positionX = positionX
        this.positionY = positionY
        this.size = size
    
        this.duration = getRandomBetween(options.durationMin, options.durationMax)
        this.limit = options.moveLimit
        this.timer = 0
    
        this.red = red
        this.green = green
        this.blue = blue
        this.opacity = opacity
    
        this.color = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',+' + this.opacity + ')'
      }
      function MouseParticle (positionX, positionY, size, red, green, blue, opacity) {
        this.positionX = mousePositionX
        this.positionY = mousePositionY
        this.size = size
    
        this.red = red
        this.green = green
        this.blue = blue
        this.opacity = opacity
    
        this.color = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',+' + this.opacity + ')'
      }
      Particle.prototype.animateTo = function (newX, newY) {
        var duration = this.duration
    
        var animatePosition = function (newPosition, currentPosition) {
          if (newPosition > currentPosition) {
            var step = (newPosition - currentPosition) / duration
            newPosition = currentPosition + step
          } else {
            step = (currentPosition - newPosition) / duration
            newPosition = currentPosition - step
          }
    
          return newPosition
        }
    
        this.positionX = animatePosition(newX, this.positionX)
        this.positionY = animatePosition(newY, this.positionY)
    
        // generate new vector
    
        if (this.timer === this.duration) {
          this.calculateVector()
          this.timer = 0
        } else {
          this.timer++
        }
      }
      Particle.prototype.updateColor = function () {
        this.color = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',+' + this.opacity + ')'
      }
      Particle.prototype.calculateVector = function () {
        var distance
        var newPosition = {}
        var particle = this
    
        var getCoordinates = function () {
          newPosition.positionX = getRandomBetween(0, window.innerWidth)
          newPosition.positionY = getRandomBetween(0, window.innerHeight)
    
          distance = getDistance(particle, newPosition)
        }
    
        // eslint-disable-next-line no-unmodified-loop-condition
        while ((typeof distance === 'undefined') || (distance > this.limit)) {
          getCoordinates()
        }
    
        this.vectorX = newPosition.positionX
        this.vectorY = newPosition.positionY
      }
      Particle.prototype.testInteraction = function () {
        if (!options.drawConnections) return
        var closestElement
        var distanceToClosestElement = maximumPossibleDistance
        for (var x = 0; x < objects.length; x++) {
          var testedObject = objects[x]
          var distance = getDistance(this, testedObject)
          if ((distance < distanceToClosestElement) && (testedObject !== this)) {
            distanceToClosestElement = distance
            closestElement = testedObject
          }
        }
        if (closestElement) {
          ctx.beginPath()
          ctx.moveTo(this.positionX + this.size / 2, this.positionY + this.size / 2)
          ctx.lineTo(closestElement.positionX + closestElement.size * 0.5, closestElement.positionY + closestElement.size * 0.5)
          ctx.strokeStyle = 'rgba(' + options.connectionRed + ',' + options.connectionGreen + ',' + options.connectionBlue + ',' + options.connectionOpacity + ')'
          ctx.stroke()
          lines++
        }
      }
      MouseParticle.prototype.testInteraction = function () {
        if (options.mouseInteractionDistance === 0) return
    
        var closestElements = []
        // var distanceToClosestElement = maximumPossibleDistance;
    
        for (var x = 0; x < objects.length; x++) {
          var testedObject = objects[x]
          var distance = getDistance(this, testedObject)
    
          if ((distance < options.mouseInteractionDistance) && (testedObject !== this)) {
            closestElements.push(objects[x])
          }
        }
    
        for (var i = 0; i < closestElements.length; i++) {
          if (options.drawMouseConnections) {
            var element = closestElements[i]
            ctx.beginPath()
            ctx.moveTo(this.positionX, this.positionY)
            ctx.lineTo(element.positionX + element.size * 0.5, element.positionY + element.size * 0.5)
            ctx.strokeStyle = 'rgba(' + options.mouseConnectionRed + ',' + options.mouseConnectionGreen + ',' + options.mouseConnectionBlue + ',' + options.mouseConnectionOpacity + ')'
            ctx.stroke()
            lines++
          }
          if (options.mouseGravity) {
            closestElements[i].vectorX = this.positionX
            closestElements[i].vectorY = this.positionY
          }
        }
      }
      Particle.prototype.updateAnimation = function () {
        this.animateTo(this.vectorX, this.vectorY)
        this.testInteraction()
        ctx.fillStyle = this.color
        ctx.fillRect(this.positionX, this.positionY, this.size, this.size)
      }
      MouseParticle.prototype.updateAnimation = function () {
        this.positionX = mousePositionX
        this.positionY = mousePositionY
        this.testInteraction()
      }
      var createParticles = function () {
        // create mouse particle
        mouseElement = new MouseParticle(0, 0, options.initialSize, 255, 255, 255)
        for (var x = 0; x < options.particlesNumber; x++) {
          var randomX = Math.floor((Math.random() * window.innerWidth) + 1)
          var randomY = Math.floor((Math.random() * window.innerHeight) + 1)
          var particle = new Particle(randomX, randomY, options.initialSize, options.red, options.green, options.blue, options.opacity)
          particle.calculateVector()
          objects.push(particle)
        }
      }
      var updatePosition = function () {
        for (var x = 0; x < objects.length; x++) {
          objects[x].updateAnimation()
        }
        // handle mouse
        mouseElement.updateAnimation()
      }
      window.onmousemove = function (e) {
        mousePositionX = e.clientX
        mousePositionY = e.clientY
      }
      var clearCanvas = function () {
        ctx.clearRect(0, 0, window.innerWidth, window.innerHeight)
      }
      var lastCalledTime
      var fps
      var averageFps
      var averageFpsTemp = 0
      var averageFpsCounter = 0
    
      function requestFps () {
        if (!lastCalledTime) {
          lastCalledTime = Date.now()
          fps = 0
          return
        }
        var delta = (new Date().getTime() - lastCalledTime) / 1000
        lastCalledTime = Date.now()
        fps = Math.floor(1 / delta)
    
        averageFpsTemp = averageFpsTemp + fps
        averageFpsCounter++
        if (averageFpsCounter === 5) {
          averageFps = Math.floor(averageFpsTemp / 5)
          averageFpsCounter = 0
          averageFpsTemp = 0
        }
        if (!averageFps) {
    
        } else if (averageFps < 10) {
    
        }
      }
      var loop = function () {
        clearCanvas()
        updatePosition()
        ctx.fillStyle = '#fff'
        // ctx.fillText("FPS: " + fps + " lines: " + lines + " Average FPS: " + averageFps , 10, 20);
        lines = 0
        requestAnimationFrame(loop)
        requestFps()
      }
      initAnimation()
      loop()
      return lines
    }
    
    

    2.引入canvas.js,实现效果

    <template>
      <div class="canvas-page">
        <canvas></canvas>
      </div>
    </template>
    <script>
    import { canvas } from '../plugins/canvas'
    export default {
      name: 'CanvasPage',
      mounted () {
        canvas(document.getElementsByTagName('canvas')[0])
      }
    }
    </script>
    <style lang="less" scoped>
    .canvas-page {
      height: 100vh;
      width: 100vw;
      background-size: cover;
      position: relative;
      background-color: #474747;
      background-image: radial-gradient(circle at 2% 60%, #27278f, transparent 100%),
        radial-gradient(circle at 98% 70%, #000c91, transparent 100%),
        radial-gradient(circle at 50% 50%, #ed68ed, transparent 100%);
      canvas {
        position: absolute;
        left: 0;
        top: 0;
        background: transparent;
        z-index: 15;
      }
    }
    </style>
    
    

    附:canvas速查表 http://canvas.migong.org/html5-canvas

    展开全文
  • sign-canvas 一个基于canvas开发,封装于Vue组件的通用手写签名板(电子签名板),支持pc端和移动端; 同时支持重新签名,覆盖签名,下载,保存等 github地址:https://github.com/mose-x/vue-sign-canvas.git ...
  • canvas绘图工具

    万次阅读 2019-01-21 15:34:36
    关于canvas绘图,在html页面上太方便了。为什么不用SVG呢?SVG大量的操作DOM元素你会发现网页的内存一下就达到几个G非常恐怖,更别说应用到移动端了。百度取了不少经,什么画板涂鸦只是小把戏缺乏实用性,灵活性。...
  • 学习HTML5 Canvas这一篇文章就够了

    万次阅读 多人点赞 2017-06-16 20:57:43
    一、canvas简介&amp;amp;lt;canvas&amp;amp;gt; 是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行...
  • Android Canvas绘图描述Android Canvas 方法总结

    万次阅读 多人点赞 2018-04-23 00:17:47
    Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。今天我们主要要了解的是2D相关的,如果你想看3D的话那么...他们提供了图形处理相关的: Canvas、ColorFilter、Point(点)和...
  • Canvas线条动画

    千次阅读 多人点赞 2020-09-03 19:23:39
    Canvas线条动画  简单的Canvas动画,代码只有71行,试试吧!没有谁天生就会,用这个动画,做为你的Canvas小结。 如果你觉得我的代码还算有趣,在你的学习中能有所帮助,请查看我的置顶文章,我由衷感谢! <!...
  • canvas的使用

    万次阅读 2020-03-09 14:15:42
    文章目录一、canvas在移动端自适应大小canvas坑1:设置canvas的css的宽高会导致你的填充内容被拉伸canvas坑1解决办法:解决后的代码与效果如下:canvas坑2:不能设置css属性如何让它自适应?canvas坑2解决办法:二、...
  • canvas画数字

    千次阅读 2017-02-17 16:07:15
    canvas
  • [Canvas系列]Canvas画布系列教程

    千次阅读 2016-12-11 15:13:39
    canvas系列[Canvas系列]Canvas基本概念_01[Canvas系列]Canvas简单线条绘制_02[Canvas系列]Canvas填充与渐变_03[Canvas系列]Canvas绘制圆弧形状_04[Canvas系列]Canvas绘制曲线之ARCTO_05[Canvas系列]Canvas绘制...
  • 自定义控件之绘图篇(四):canvas变换与操作

    万次阅读 多人点赞 2014-09-05 15:05:36
    前言:前几篇讲解了有关canvas绘图的一些操作,今天更深入一些,讲讲对画布的操作,这篇文章不像前几篇那么容易理解,如果以前没有接触过画布的童鞋可能比较难以理解,为什么会这样。我尽量多画图,让大家更清晰明白...
  • 将图片画到canvas 上的几种方法

    万次阅读 多人点赞 2018-09-22 01:34:13
    任何的知识体系,都是由小的知识体系构成,你要想成为高手 ...canvas 画图片的 第一种,就是在画布的坐标上,直接将图片画到上面去,此时 假如图片大小超出了画布,图片也不缩放 /*3参数*/ ...
  • canvas的drawImage方法参数详解

    万次阅读 2017-07-15 17:24:01
    canvas
  • canvas乱码的处理

    万次阅读 2020-05-29 11:18:40
    canvas实现图表功能时,如果我们从网上copy别人的demo时,运行发现中文乱码了。 1、当你的页面是.html格式的乱码问题 解决: 将复制的demo内容先通过记事本以utf-8的编码方式保存,然后再粘贴到自己的项目中。 2、...
  • [Canvas画图系列]Canvas基本概念_01

    千次阅读 2016-12-11 15:19:06
    所以,如果你想学习Canvas画图,你必须要有Javascript基础。另外,画图嘛,总有一些图像方面的术语和知识点,所以如果你有过做图或美工经验,学习Canvas会更容易。Canvas,意为画布也。而Html5中的Canvas也真的跟...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 108,229
精华内容 43,291
热门标签
关键字:

canvas