zoukankan      html  css  js  c++  java
  • HTML5 CANVAS 高级

    加载图片

    获取图像有三种方式:

    a : createImageData(),没有效率,一个像素一个像素的绘制;

    b :

    var img= document.getElementById("imageId");

    c : 加载外部图片,这种方式需要等待外部图片加载完毕:

    var img = new Image();

    img.src = "some/location/imgname.jpg";

    canvasのlengthとwidth

    不要在css样式中这顶canvas的长和宽,它极有可能会导致canvas的显示不正常。

    <canvas width="100px" height="200px"></canvas>

    以上代码会正常显示canvas,canvas里面的内容也可以正常显示。

    如果加上

    canvas {
    width: 200px;
    height: 400px;
    }

    以上样式的话,那么canvas会被拉伸到200px*400px。换句话说,canvas确实是css指定的那么大,但是已经经过缩放或者拉伸了。

    绘图

    在指定的location(x, y)处画image图片。图片大小为图片的实际大小。

    context.drawImage(image, x, y);

    在指定的location(x, y)处画image图片。图片会被进行拉伸或压缩,大小为width*height,

    context.drawImage(image, x, y, width, height);

    在指定的location(x, y)处画image图片。图片已经被剪裁了,剪裁的位置为原始图片的(x_location, y_location)处,剪裁大小为x_width*y_width。图片会压缩为width*height大小。

    context.drawImage(image, x_location, y_location, x_width, y_width, x, y, width, height);

    写文本: 挺有用的

    首先设置字体相关的信息:

    context.font,用来设定文本的字体,如: "italic bold 20px Arial, Consolas"

    context.textBaseline, 用来设定文本的位置。 "alphabetic|top|hanging|middle|ideographic|bottom",这些值是可以选择的。

    如下用来填充文本,

    context.fillStyle = "#112233";
    context.fillText("something want to wirte", x, y); 

    如下用来描文本的边,

    context.strokeStyle = "blue";
    context.strokeText("something want to wirte", x, y);

    阴影

    context.shadowColor = "#aabbcc";  // 设置阴影的颜色

    context.shadowBlur = 10;  // 设置阴影的锐利(官方的说话)程度,取值在1~20之间就可以,一般大于3

    context.shadowOffsetX = 10;  // X轴方向上阴影的距离

    context.shadowOffsetY = 10;  // Y轴方向上阴影的距离

    阴影的想象返回包括,文本,图形,图片等。

    填充图案

    可能就是所谓的背景图片了

    var pattern;
    var bgimg = new Image();
    
    bgimg.onload = function(){
      pattern = context.createPattern(bgimg, "repeat|repeat-x|repeat-y");
    }
    
    context.fillStyle = pattern;
    // context.fillRect(0, 0, canvas.width, canvas.height);
    context.rect(0, 0, canvas.width, canvas.height);
    context.fill();

    渐变色背景

    线性渐变

    var linear = context.createLinearGradient(x_start, y_start, x_end, y_end);

    (x_start, y_start)和(x_end, y_end)指定了渐变色的起点和终点,两点之间连成一条线。

    linear.addColorStop(0, "color1");

    linear.addColorStop(0.5, "color2");

    linear.addColorStop(1, "color3");

    context.fillStyle = linear;

    起点之前的颜色为color1指定的颜色,终点之后的颜色为color3指定的颜色。

    context.drawSomthing();

    画完图之后,调用:context.fill();渐变背景色就显示出来了。。。

    放射性渐变

    var radial = context.createRadialGradient(x_start, y_start, radius_start, x_end, y_end, radius_end);

    其它的基本一样。

    canvas交互

    canvas并不记录其上有什么图形,什么线条。它什么也不知道,仅仅是一个图片,甚至连一个容器都算不上。

    那么如何使canvas具有交互能力呢?利用javascript!

    首先javascript的构造函数:

    function Circle(x, y, radius){
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.color = "pink";
    }

    真心不了解javascript!以上代码中的this.x中的x到底是个什么东西?什么时候出现的,什么时候赋的值?

    按照小猿的理解,这个函数创建的时候,给它分配了空间,而其内部写的所有的this.something中的something都是它的成员变量。

    为什么要写这个东西呢?他能干吗?

    我们用它来保留canvas中所谓对象的状态!

    怎么保存,要是有很多个呢?

    在javascript中设定全部变量,这个变量是一个数组,声明如: var circles = [];

    如此一来,circles就成了真正的容器了。

    你说这些东西有毛用啊?

    canvas的碰撞会有很大的用途!

    假如,我们鼠标点击了canvas中的一个点,需要判断这个点是否碰撞上了一个圆。

    var circle = new Circle(100, 100, 30);
    
    function clickCheck(event){
        var p_x = event.pageX - canvas.offsetLeft;
        var p_y = event.pageY - canvas.offsetTop;
    
        // 检测(p_x, p_y)是否在circle范围内
        var distance = Math.sqrt(Math.pow(p_x - circle.x, 2) + Math.pow(p_y - circle.y, 2));
    if (distance > circle)
    // 在圈里
    else
    // 不在圈里

    拖动一个圆圈跑

    如果一个像素一个像素的移动,那么看上去就是在拽着图片跑。

    var mouseDown;
    window.onload = function(){
        // some other things
    
        canvas.onmousedown = mousecheck;
        canvas.onmousemove = circlemove;
        canvas.onmouseup = mousecheck;
    }
    
    function circlemove(e){
        if (mousedown){
            var x = e.pageX - canvas.offsetLeft;
            var y = e.pageY - canvas.offsetTop;
    
            circle.x = x;
            circle.y = y;
    
            drawCanvas();
        }
    }
    
    function drawCanvas(){
        // start
        context.beginPath();
        context.arc(circle.x, circle.y, circle.radius);
        context.fillStyle = "#121212";
        context.fill();
        context.stroke();
    }

    动画

    动画的关键是如何让它动,在任何一个固定的时间点,所有的东西都是静止的!只不过随着时间的推移,这些东西的位置发生了变化而已。

    整的像那么回事儿似的。好吧,我错了。

    所以我们要做的就是在任意一个时间点都画canvas。需要用到的就是javascript的setTimeout()或者setInterval()。

    setTimeout(functionName, millseconds);在指定的millseconds之后,执行functionName指定的函数。

    通常functionName中也包含setTimeout,以保证动画执行下去。

    setInterval(functionName, millseconds);每隔millseconds之后,执行functionName指定的函数。

    这个方法有一个缺陷,就是不能保证functionName指定的function能够在millseconds指定的时间内完成,如果不能完成的话就会出现所谓的卡顿现象。

    这个方法有一个有点,就是只需要调用一次即可,当不想再执行的时候,clearInterval()方法可以让它停止。

    示例:

    var x_position = 10;
    var y_postition = 0;
    
    window.onload = function(){
        // get canvas, context
    
        setTimeout(drawFrame, 200);
    }
    
    function dramFrame(){
        context.clearRect(0, 0, canvas.width, canvas.height);
        
        context.beginPath();
    
        context.fillStyle = "#343434";
        context.fillRect(x_position, y_position, 10, 20);
        context.strokeStyle = "#999999";
        context.strokeRect(x_position, y_position, 10, 20);
    
        y_position += 1;
    
        if ( y_position < canvas.height ) setTimeout(dramFrame, 200);
    
    }

    稍稍总结一下:

    动画中肯定要有一个被重复调用的function,而这个function基本上都是在window.onload或者image.onload中调用的。

    而这个function所做的无外乎,清除画布,把画布中所有的对象重新绘制。

    按键响应

    var dx = 0;
    var dy = 0;
    function keyPress(event) {
        // 先让图片停止下来
        dx = 0;
        dy = 0;
    
        if (event.keyCode == 37)
            dx = -1;
        if (event.keyCode == 38)
            dy = -1;
        
        ...
    }

    颜色碰撞:它相对于距离计算来说稍微复杂一点,但是仍然也是十分有效的方式。

    先说说颜色,我们知道rgb(254,100,80),也应该知道rgba(254, 100, 80, 0.5)。这是数值都是准确的,也就是说改变其中任何一个值都会造成所表示的颜色不一致。

    canvas就利用这一点来实现的颜色碰撞。其实也有些弊端,一会儿再说。

    var imgData = context.getImagedata(0, 0, 100, 50);

    以上代码获得(0,0)这个位置开始,沿X方向走100,沿Y方向走50这一块儿canvas图片对应的图片数据。

    imgData的data属性是一个数组,其个数是其中像素点个数*4。因为每一个像素点都由4个值组成。

    这里需要注意的是最后一个值也是[0, 255)里的,而不是[0, 1]。

    关键就是r = xxx; g = yyy; b = xxx;

    而如果rgb正好是某一个值,那么就算碰上了。。。

      弊端: 如果图片中有相同的颜色,但是可以走的话就没治了!

  • 相关阅读:
    5-python基础—获取某个目录下的文件列表(适用于任何系统)
    Automated, Self-Service Provisioning of VMs Using HyperForm (Part 1) (使用HyperForm自动配置虚拟机(第1部分)
    CloudStack Support in Apache libcloud(Apache libcloud中对CloudStack支持)
    Deploying MicroProfile-Based Java Apps to Bluemix(将基于MicroProfile的Java应用程序部署到Bluemix)
    Adding Persistent Storage to Red Hat CDK Kit 3.0 (在Red Hat CDK Kit 3.0添加永久性存储)
    Carve Your Laptop Into VMs Using Vagrant(使用Vagran把您笔记本电脑刻录成虚拟机)
    使用Python生成一张用于登陆验证的字符图片
    Jupyter notebook的安装方法
    Ubuntu16.04使用Anaconda5搭建TensorFlow使用环境 图文详细教程
    不同时区的换算
  • 原文地址:https://www.cnblogs.com/voctrals/p/4134777.html
Copyright © 2011-2022 走看看