精华内容
下载资源
问答
  • 这次给大家带来怎样canvas实现自定义头像功能,用canvas实现自定义头像功能的注意事项有哪些,下面就是实战案例,一起来看一下。在最前:前两天老大跟我说老虎官网上那个自定义头像的功能是flash实现的,没有...

    这次给大家带来怎样用canvas实现自定义头像功能,用canvas实现自定义头像功能的注意事项有哪些,下面就是实战案例,一起来看一下。

    写在最前:

    前两天老大跟我说老虎官网上那个自定义头像的功能是flash实现的,没有安装过的还得手动去“允许”falsh的运行。所以让我用canvas实现一个一样的功能,嘿嘿,刚好最近也在研究canvas,所以欣然答应(其实,你没研究过难道就不答应么,哈哈哈哈哈~)

    成果展示:

    f05f3f5f6f4e0d2156b7cb8790824cb4.gif

    Git地址:https://github.com/ry928330/portraitDIY

    功能说明:拖拽左侧小方框,或者是鼠标放在小方框右下角,点击拉伸方框,方框覆盖部分的图片被自动截取下来,然后再在右侧的多个容器里面重绘。

    输入宽高,自定义你需要订制的头像大小,目前只支持宽高相同的头像图片。

    实现细节:

    因为你要对图片所在的区域进行截图,所以你得制作一张canvas,盖在图片所在的区域。这里,我们给出了一个函数,根据传入的DOM里面元素的类名创建相同位置的canvas,盖在原来的DOM元素上面:function createCanvasByClassName(tag) {

    var canvasInitialWidth = $('.' + tag).width();

    var canvasInitialHeight = $('.' + tag).height();

    var left = $('.' + tag).offset().left - $('.' + tag).parent('.portraitContainer').offset().left + 1;

    var top = $('.' + tag).offset().top - $('.' + tag).parent('.portraitContainer').offset().top + 1;

    //var left = $('.' + tag).offset().left + 1;

    //var top = $('.' + tag).offset().top + 1;

    clearCanvasObj.left = $('.' + tag).offset().left + 1;

    clearCanvasObj.top = $('.' + tag).offset().top + 1;

    // clearCanvasObj.left = left;

    // clearCanvasObj.top = top;

    var canvasElement = $('');

    var randomNum = Math.floor(getRandom(0, 10000));

    clearCanvasObj.canvasId = randomNum;

    canvasElement.attr({

    id: 'canvas',

    width: canvasInitialWidth,

    height: canvasInitialHeight

    });

    canvasElement.css({

    position: 'absolute',

    top: top,

    left: left

    });

    //$('body').append(canvasElement);

    var appendEle = $('.portraitContainer').append(canvasElement);

    var canvas = document.getElementById('canvas');

    var ctx = canvas.getContext('2d');

    //ctx.fillStyle = "rgba(211,211,216,0.5)";

    ctx.clearRect(0, 0, canvasInitialWidth, canvasInitialHeight);

    ctx.fillStyle = "rgba(0,0,0, 0.4)";

    ctx.fillRect(0, 0, canvasInitialWidth, canvasInitialHeight);

    return canvas;

    }

    有了这张canvas你就可以在你图片所在区域肆意的操作了。首先,降整个区域画上一个浅黑色的阴影,然后再擦除初始小方框区域里面的颜色。然后给整个页面添加mousedown,mousemove,mouseup事件,他们所做的功能就跟你在页面中实现一个拖拽的功能类似,这里重点说下mousemove里面做的操作,代码如下:function mousemoveFunc(event) {

    /* Act on the event */

    var nowMouseX = event.clientX - clearCanvasObj.left;

    var nowMouseY = event.clientY - clearCanvasObj.top;

    if (nowMouseX >= clearCanvasObj.xStart && nowMouseX <= clearCanvasObj.xStart + clearCanvasObj.width && nowMouseY >= clearCanvasObj.yStart && nowMouseY <= clearCanvasObj.yStart + clearCanvasObj.height) {

    clearCanvasObj.isCanvasArea = true;

    //clearCanvasObj.isRightCorner = false;

    imgContainerCanvas.style.cursor = 'move';

    } else if ((nowMouseX >= clearCanvasObj.xStart + clearCanvasObj.width - 10) && (nowMouseX <= clearCanvasObj.xStart+ clearCanvasObj.width + 10)

    && (nowMouseY >= clearCanvasObj.yStart + clearCanvasObj.height - 10) && (nowMouseY <= clearCanvasObj.yStart + clearCanvasObj.height + 10)) {

    clearCanvasObj.isCanvasArea = true;

    //clearCanvasObj.beginDraw = false;

    imgContainerCanvas.style.cursor = 'se-resize';

    }

    else {

    clearCanvasObj.isCanvasArea = false;

    //clearCanvasObj.isRightCorner = false;

    imgContainerCanvas.style.cursor = 'default';

    }

    var outerDomWidth = $(".imgContainer").width();

    var outerDomHeight = $(".imgContainer").height();

    var xDistance = event.clientX - clearCanvasObj.mouseX;

    var yDistance = event.clientY - clearCanvasObj.mouseY;

    //var outerCTX = canvas.getContext('2d');

    //移动小方框

    if (clearCanvasObj.beginDraw && clearCanvasObj.isCanvasArea && !clearCanvasObj.isRightCorner) {

    ry_CTX.fillStyle = clearCanvasObj.color;

    // console.log('1', clearCanvasObj.xStart, clearCanvasObj.yStart)

    ry_CTX.fillRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);

    //outerCTX.fillRect(0, 0, canvas.width, canvas.height);

    clearCanvasObj.xStart += xDistance;

    clearCanvasObj.yStart += yDistance;

    //判断方框是否达到边界

    if (clearCanvasObj.xStart <= 0) {

    clearCanvasObj.xStart = 0;

    }

    if (clearCanvasObj.yStart <= 0) {

    clearCanvasObj.yStart = 0;

    }

    if ((clearCanvasObj.xStart + clearCanvasObj.width) >= outerDomWidth) {

    clearCanvasObj.xStart = outerDomWidth - clearCanvasObj.width;

    }

    if ((clearCanvasObj.yStart + clearCanvasObj.height) >= outerDomHeight) {

    clearCanvasObj.yStart = outerDomHeight - clearCanvasObj.height;

    }

    // console.log('2', clearCanvasObj.xStart, clearCanvasObj.yStart)

    ry_CTX.clearRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);

    produceSmallPic(clearCanvasObj.xStart+clearCanvasObj.left, clearCanvasObj.yStart+clearCanvasObj.top, clearCanvasObj.width, clearCanvasObj.height, imageURL)

    clearCanvasObj.mouseX = event.clientX;

    clearCanvasObj.mouseY = event.clientY;

    }

    //拖拽小方框

    if (clearCanvasObj.isRightCorner) {

    ry_CTX.fillStyle = clearCanvasObj.color;

    ry_CTX.fillRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);

    var realDistance = Math.min(xDistance, yDistance)

    clearCanvasObj.width += realDistance;

    clearCanvasObj.height += realDistance;

    //拖动时边界条件的判断

    if (clearCanvasObj.xStart + clearCanvasObj.width >= outerDomWidth) {

    clearCanvasObj.width = outerDomWidth - clearCanvasObj.xStart;

    clearCanvasObj.height = outerDomWidth - clearCanvasObj.xStart;

    }

    if (clearCanvasObj.yStart + clearCanvasObj.height >= outerDomHeight) {

    clearCanvasObj.width = outerDomHeight - clearCanvasObj.yStart;

    clearCanvasObj.height = outerDomHeight - clearCanvasObj.yStart;

    }

    if (clearCanvasObj.width <= 10) {

    clearCanvasObj.width = 10;

    }

    if (clearCanvasObj.height <= 10) {

    clearCanvasObj.height = 10;

    }

    ry_CTX.clearRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);

    produceSmallPic(clearCanvasObj.xStart+clearCanvasObj.left, clearCanvasObj.yStart+clearCanvasObj.top, clearCanvasObj.width, clearCanvasObj.height, imageURL);

    clearCanvasObj.mouseX = event.clientX;

    clearCanvasObj.mouseY = event.clientY;

    }

    }

    函数里面,你需要注意拖拽的边界条件,一个是方框不能拖到图片所在DOM外的边界;另外一个就是当你鼠标放在小方框所在的区域改变鼠标的样式。方框在拖动的过程中,我们不断重绘方框移动的区域(也就是不断的画上阴影),然后在新的位置调用clearRect函数,重新擦出一个小方框出来。在拖拽或是拉伸的过程中,我们会不断调用produceSmallPic函数,在右边的容器(每个容器都是一个canvas)里面不断根据容器大小重绘出所需的头像。代码如下:function produceSmallPic(imageURL,left, top, width, height) {

    var img = new Image();

    img.src = imageURL;

    var targetCtx = new Array();

    var targetCanvas = null;

    img.onload = function() {

    portraitGroupsArr.forEach(function(item, index) {

    targetCanvas = document.getElementById(item.class);

    targetCtx.push(targetCanvas.getContext('2d'));

    targetCtx[index].clearRect(0,0, item.width, item.height);

    targetCtx[index].drawImage(img, left - clearCanvasObj.left, top - clearCanvasObj.top, width, height, 0, 0 , item.width, item.height);

    })

    }

    }

    我们说下这个函数的作用,这里我们要注意一个参数imageURL,这个URL是由图片所在的DOM转化来的。因为你要把DOM所在的区域变成一张图片,这样你才能在利用drawImage函数截取你所需要的区域。所以我们先利用html2canvas库函数讲图片所在的DOM转化为canvas,这张canvas的内容是包含你所要截取的图片的,然后把这张canvas转化为图片取得图片地址imageURL,代码如下:html2canvas(document.getElementById('imgContainer'), {

    onrendered: function(canvas) {

    var imageURL = canvasTransToImage(canavs);

    ...

    }

    })

    function canvasTransToImage(canvas) {

    var imageURL = canvas.toDataURL('image/png');

    return imageURL;

    }

    接着,你就可以便利右侧的canvas容器,讲图片重回到里面了,整个过程就这样结束,回头看来是不是很简单。

    相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

    推荐阅读:

    展开全文
  • 自定义了一个View,在初始化时该View会先画一部分图形,然后连接服务器,...我在自定义View的类里,设置了一个Canvas变量can,在onDraw(Canvas canvas )方法的最后一行了“can=canvas",可是得到的can变量却是null。
  • 自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我一篇关于怎样利用HTML5 Canvas制作游戏的入门教程。花了一点时间考虑怎么着手写这篇文章后,我决定先实现一个我觉得最最简单的游戏,...
    原文连接: How To Make A Simple HTML5 Canvas Game

    自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML5 Canvas制作游戏的入门教程。花了一点时间考虑怎么着手写这篇文章后,我决定先实现一个我觉得最最简单的游戏,然后一行代码一行代码地进行讲解。

    让我们开始吧,首先看看game.js,当然你也可以先玩玩这个游戏(译注:附件是游戏源码,用浏览器打开其中的index.html就可以玩了,或者也可以到 lostdecadegames官网上去玩)。

    附件下载地址: simple_canvas_game



    1. 创建一个Canvas对象

    // Create the canvas
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    canvas.width = 512;
    canvas.height = 480;
    document.body.appendChild(canvas);

    我们首先要做的是创建一个canvas对象。可以用JavaScript或HTML来做,都非常简单。此处我用的是JS。当创建了canvas之后,我们就可以获取它的上下文对象(context)、设置尺寸,并且把它加到当前文档中。

    2. 载入图片

    // Background image
    var bgReady = false;
    var bgImage = new Image();
    bgImage.onload = function () {
        bgReady = true;
    };
    bgImage.src = "images/background.png";

    游戏需要图像,所以让我们载入一些图片吧。我想尽量简单化,所以只用了Image对象来做,当然,还可以将载入图像的功能封装成一个类或别的任何形式。代码中的bgReady用来标识图片是否已完全载入,只有当图片载入完成后,我们才能使用它,如果在载入完成前就对其进行绘制或渲染,JS将会报一个DOM error的错误。

    我们会用到三张图片(背景、英雄、怪物),每张图片都需要这样处理。

    3. 定义游戏要使用的对象

    // Game objects
    var hero = {
        speed: 256, // movement in pixels per second
        x: 0,
        y: 0
    };
    var monster = {
        x: 0,
        y: 0
    };
    var monstersCaught = 0;

    定义一些变量,稍后会用到。hero对象的speed属性表示英雄的移动速度(像素/秒);monster对象不会移动,所以仅仅具有一对坐标;monstersCaught表示玩家抓住的怪物数量。

    4. 处理玩家输入

    // Handle keyboard controls
    var keysDown = {};
    addEventListener("keydown", function (e) {
         keysDown[e.keyCode] = true;
    }, false);
    addEventListener("keyup", function (e) {
         delete keysDown[e.keyCode];
    }, false);

    现在进行输入的处理。(对具有web开发背景的人来说,这是目前为止第一个具有挑战性的部分)对一般的网页来说,当用户开始输入时,可能需要马上开始播放动画或请求数据。但在这里,我们想让游戏逻辑在一个单独的地方对游戏中发生的事情进行处理。为此我们需要将用户输入保存下来以备稍后处理,而不是立即处理。

    我们通过简单地将事件对应的键编码(keyCode)保存在keysDown变量中来实现。如果该变量中具有某个键编码,就表示用户目前正按下这个键。简单吧!

    5. 新游戏

    // Reset the game when the player catches a monster
    var reset = function () {
         hero.x = canvas.width / 2;
         hero.y = canvas.height / 2;
    
         // Throw the monster somewhere on the screen randomly
         monster.x = 32 + (Math.random() * (canvas.width - 64));
         monster.y = 32 + (Math.random() * (canvas.height - 64));
    };

    通过调用reset函数来开始新游戏。该函数将英雄(即玩家角色)放到屏幕中间,然后随机选择一个位置来安置怪物。

    6. 更新对象

    // Update game objects
    var update = function (modifier) {
        if (38 in keysDown) { // Player holding up
            hero.y -= hero.speed * modifier;
        }
        if (40 in keysDown) { // Player holding down
            hero.y += hero.speed * modifier;
        }
        if (37 in keysDown) { // Player holding left
            hero.x -= hero.speed * modifier;
        }
        if (39 in keysDown) { // Player holding right
            hero.x += hero.speed * modifier;
        }
    
        // Are they touching?
        if (
            hero.x <= (monster.x + 32)
                && monster.x <= (hero.x + 32)
                && hero.y <= (monster.y + 32)
                && monster.y <= (hero.y + 32)
        ) {
             ++monstersCaught;
             reset();
        }
    };

    这是update函数,游戏每隔一定时间会调用它一次。它所做的第一件事情是检查用户是否按下了上下左右四个箭头键。如果是,就将我们的英雄向相应的方向移动。

    update有一个modifier参数,这看起来好像有点奇怪。你会在游戏的主函数即main函数中看到它,不过我在这儿先解释一下。modifier参数是一个从1开始的与时间相关的数。如果间隔刚好为1秒时,它的值就会为1,英雄移动的距离即为256像素(英雄的速度为256像素/秒);而如果间隔是0.5秒,它的值就为0.5,即英雄移动的距离为其速度的一半,以此类推。通常update函数调用的间隔很短,所以modifier的值很小,但用这种方式能够确保不管代码执行的速度怎么样,英雄的移动速度都是相同的。

    我们已经实现了根据用户的输入来移动英雄,但我们还可以在移动英雄时对其进行检查,以确定是否有其他事件发生。例如:英雄是否与怪物发生了碰撞——当英雄与怪物发生碰撞时,我们为玩家进行计分(monstersCaught加1)并重置游戏(调用reset函数)。

    7. 渲染对象

    // Draw everything
    var render = function () {
        if (bgReady) {
             ctx.drawImage(bgImage, 0, 0);
        }
    
        if (heroReady) {
             ctx.drawImage(heroImage, hero.x, hero.y);
        }
    
        if (monsterReady) {
             ctx.drawImage(monsterImage, monster.x, monster.y);
        }
    
        // Score
        ctx.fillStyle = "rgb(250, 250, 250)";
        ctx.font = "24px Helvetica";
        ctx.textAlign = "left";
        ctx.textBaseline = "top";
        ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
    };

    当你能够看到你的行动时游戏才会变得更有趣,所以让我们在屏幕上绘制吧。首先我们将背景图片绘制到canvas,然后是英雄和怪物。注意顺序很重要,因为任何位于表层的图片都会将其下面的像素覆盖掉。

    接下来是文字,这有些不同,我们调用fillText函数显示玩家的分数。因为不需要复杂的动画或者对文字进行移动,所以只是绘制一下就ok了。

    8. 游戏主循环

    // The main game loop
    var main = function () {
        var now = Date.now();
        var delta = now - then;
    
        update(delta / 1000);
        render();
    
        then = now;
    };

    游戏的主循环用来控制游戏流程。首先我们要获得当前的时间,这样我们才能计算时间差(自上次循环以来经过的时间)。然后计算modifier的值并交给update(需要将delta除以1000以将其转换为毫秒)。最后调用render并更新记录的时间。

    更多关于游戏循环的内容见“Onslaught! Arena Case Study”。

    9. 开始游戏吧

    // Let's play this game!
    reset();
    var then = Date.now();
    setInterval(main, 1); // Execute as fast as possible

    快完成了,这是最后一段代码。首先调用reset来开始新游戏。(还记得吗,这会将英雄置中并随机安放怪物)。然后将起始时间保存到变量then中并启动游戏的主循环。

    OK!(但愿)你现在已经理解了在HTML5 Canvas中用JS来开发游戏的基础知识了。建议最好是能够自己亲自试一把!

     

    转载于:https://www.cnblogs.com/james1207/p/3297266.html

    展开全文
  • 最近学了点canvas,做了个滴滴的进度条效果,由于本人未使用过滴滴,所以不太清楚该具体效果以及该页面是怎样的。yy出了以下效果: 先从简单的圆开始吧! 代码: let c = document.getElementById("myCanvas") // ...
        

    最近学了点canvas,做了个滴滴的进度条效果,由于本人未使用过滴滴,所以不太清楚该具体效果以及该页面是怎样的。yy出了以下效果:

    clipboard.png

    先从简单的圆开始吧!

    clipboard.png

    代码:

    let c = document.getElementById("myCanvas")
    // getContext() 方法返回一个用于在画布上绘图的环境。
    let ctx = c.getContext("2d")
    // 起始一条路径,或重置当前路径
    ctx.beginPath()
    // 创建弧/曲线(用于创建圆形或部分圆)
    ctx.arc(100, 75, 50, 0, 2*Math.PI)
    // 绘制已定义的路径
    ctx.stroke()
    

    这里贴出arc()函数说明:

    context.arc(x,y,r,sAngle,eAngle,counterclockwise);
    
    

    clipboard.png

    有兴趣的同学可以进入链接查看更多属性和方法: http://caibaojian.com/html5-c...

    接下来我们绘制圆环以及动画:

    clipboard.png

    let canvas = document.getElementById('myCanvas'),
        context = canvas.getContext('2d'),
        cirX = canvas.width/2,
        cirY = canvas.height/2,
        rad = Math.PI*2/100,
        n = 0,
        r = 45;

    绘制图形并生成动画:

    function DreamLoading() {
      // clearRect() 方法清空给定矩形内的指定像素。
      context.clearRect(0,0,canvas.width,canvas.height);
      writeCircle();
      writeText(n);
      writeOrange(n);
      if(n < 100) {
        n = n + 0.1
      } else {
        n = 100;
      }
      window.requestAnimationFrame(DreamLoading);
    }
    

    当我们写window.requestAnimationFrame(回调函数)时,浏览器会在下次重绘前执行回调函数。这样就有进度条的效果了。

    画圆:

    function writeCircle() {
      // 画个圆
      // save() 方法把当前状态的一份拷贝压入到一个保存图像状态的栈中。这就允许您临时地改变图像状态,然后,通过调用 restore() 来恢复以前的值。
      context.save();
      context.beginPath();
      context.strokeStyle = "#FF8C00";
      context.arc(cirX,cirY,r,0,Math.PI*2,false);
      context.stroke();
      context.restore();
    }
    

    进度条:圆的厚边框,lineWidth自行设置

    function writeOrange(n) {
      context.save();
      context.strokeStyle = "#FF8C00";
      context.lineWidth = 3;
      context.beginPath();
      context.arc(cirX,cirY,r,-Math.PI/2,-Math.PI/2+rad*n,false);
      context.stroke();
      // restore() 方法将绘图状态置为保存值。
      context.restore();
    }
    

    文本,百分比效果:

    function writeText(n) {
      context.save();
      context.strokeStyle = '#FF8C00';
      context.font = '20px Arail';
      context.strokeText(n.toFixed() + '%', cirX-30,cirY+10);
      context.stroke();
      context.restore();
    }
    

    百分比进度条效果全部代码:

    <!doctype html>
    <html>
    <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      canvas {
        margin: 0 auto;
        display: block;
      }
    </style>
    </head>
    <body>
    <canvas id="myCanvas"></canvas>
    <script>
    window.onload = function () {
    let canvas = document.getElementById('myCanvas'),
        context = canvas.getContext('2d'),
        cirX = canvas.width/2,
        cirY = canvas.height/2,
        rad = Math.PI*2/100,
        n = 0,
        r = 45;
    function DreamLoading() {
      context.clearRect(0,0,canvas.width,canvas.height);
      writeCircle();
      writeText(n);
      writeOrange(n);
      if(n < 100) {
        n = n + 0.1
      } else {
        n = 100;
      }
      window.requestAnimationFrame(DreamLoading);
    }
    
    function writeText(n) {
      context.save();
      context.strokeStyle = '#FF8C00';
      context.font = '20px Arail';
      context.strokeText(n.toFixed() + '%', cirX-30,cirY+10);
      context.stroke();
      context.restore();
    }
    
    function writeOrange(n) {
      context.save();
      context.strokeStyle = '    #FF8C00';
      context.lineWidth = 3;
      context.beginPath();
      context.arc(cirX,cirY,r,-Math.PI/2,-Math.PI/2+rad*n,false);
      context.stroke();
      context.restore();
    }
    
    function writeCircle() {
      // 画个圆
      // stroke 边框
      // 保存当前的绘制缓冲区
      context.save();
      // 开始路径
      context.beginPath();
      context.strokeStyle = "    #FF8C00";
      context.arc(cirX,cirY,r,0,Math.PI*2,false);
      context.stroke();
      context.restore();
    }
    DreamLoading();
    }
    </script>
    </body>
    </html>
    

    倒计时效果代码:

    let minute = 1
          const Time = minute*60
          let second = 0
          render(minute, second)
          const interval = setInterval(() => {
            if (second < 60) {
              second--
              if (second < 0) {
                second = 59
                minute--
              }
            }
            if(minute == 0 && second == 0) {
                clearInterval(interval)
            }
            render(minute, second)
          },1000)
    
          function render(minute, second) {
            if (minute < 10) {
              document.querySelector('.minute').innerText = '0' + minute;
            } else {
              document.querySelector('.minute').innerText = minute;
            }
            if (second < 10) {
              document.querySelector('.second').innerText = '0' + second;
            } else {
              document.querySelector('.second').innerText = second;
            }
          }

    完整代码:

       <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <style>
        * {
          margin: 0;
          padding: 0;
        }
        .header {
          height: 44px;
          border-bottom: 1px solid #eee;
          background-color: #ddd;
          display: -webkit-flex;
          display: flex;
          align-items: center;
        }
        .header-left {
          width: 3rem;
          margin-left: 1rem;
        }
        .header-left .back {
          display: block;
          width: .8rem;
          height: .8rem;
          border-left: 1px solid red;
          border-bottom: 1px solid red;
          transform: rotateZ(45deg);
        }
        .header-middle {
          flex: 1;
          text-align: center;
        }
        .header-right {
          width: 4rem;
          margin-right: .5rem;
        }
        .content {
          width: 100%;
          height: 11rem;
          background: url(http://st2.depositphotos.com/6064568/10599/v/950/depositphotos_105993268-stock-illustration-man-holding-smartphone-in-hand.jpg);
          background-size: cover;
          position: relative;
        }
        canvas {
          margin: 0 auto;
          display: block;
        }
        .tip {
          text-align: center;
          font-size: 1.2rem;
          margin-top: -.5rem;
        }
        .time {
          /*width: 5rem;
          height: 1rem;*/
          /*position: absolute;
          top: 30%;*/
          /*left: 42%;*/
          margin: 0 auto;
          margin-top: -7rem;
        }
        .time p:first-child {
          font-size: 1.5rem;
          text-align: center;
        }
        .time p:last-child {
          font-size: .8rem;
          text-align: center;
        }
      </style>
    </head>
    <body>
      <div class="header">
        <div class="header-left">
          <i class="back"></i>
        </div>
        <div class="header-middle">
          派单中
        </div>
        <div class="header-right">
          取消订单
        </div>
      </div>
      <div class="content">
        <canvas id="canvas"></canvas>
        <div class="tip">系统选择司机</div>
        <div class="time">
          <p><span class="minute"></span>:<span class="second"></span></p>
          <p>秒倒计时</p>
        </div>
      </div>
      <script>
        window.onload = function() {
          let minute = 1
          const Time = minute*60
          let second = 0
          render(minute, second)
          const interval = setInterval(() => {
            if (second < 60) {
              second--
              if (second < 0) {
                second = 59
                minute--
              }
            }
            if(minute == 0 && second == 0) {
                clearInterval(interval)
            }
            render(minute, second)
          },1000)
    
          function render(minute, second) {
            if (minute < 10) {
              document.querySelector('.minute').innerText = '0' + minute;
            } else {
              document.querySelector('.minute').innerText = minute;
            }
            if (second < 10) {
              document.querySelector('.second').innerText = '0' + second;
            } else {
              document.querySelector('.second').innerText = second;
            }
          }
          var canvas = document.getElementById('canvas'),
              context = canvas.getContext('2d'),
              cirX = canvas.width/2,
              cirY = canvas.height/2,
              rad = Math.PI*2/(Time*Math.PI*2),
              n = 0,
              r = 45;
          function DreamLoading() {
            context.clearRect(0,0,canvas.width,canvas.height);
            writeCircle();
            // writeText(n);
            writeOrange(n);
            if(n < Time*Math.PI*2) {
              n = n + 0.105
            } else {
              n = Time*Math.PI*2;
            }
            window.requestAnimationFrame(DreamLoading);
          }
    
          // function writeText(n) {
          //   context.save();
          //   context.strokeStyle = '#FF8C00';
          //   context.font = '20px Arail';
          //   context.strokeText(n.toFixed() + '%', cirX-30,cirY+10);
          //   context.stroke();
          //   context.restore();
          // }
    
          function writeOrange(n) {
            context.save();
            context.strokeStyle = '    #FF8C00';
            context.lineWidth = 3;
            context.beginPath();
            context.arc(cirX,cirY,r,-Math.PI/2,-Math.PI/2+rad*n,false);
            context.stroke();
            context.restore();
          }
    
          function writeCircle() {
            // 画个圆
            // stroke 边框
            // 保存当前的绘制缓冲区
            context.save();
            // 开始路径
            context.beginPath();
            context.strokeStyle = "    #FF8C00";
            context.arc(cirX,cirY,r,0,Math.PI*2,false);
            context.stroke();
            context.restore();
          }
          DreamLoading();
        }
      </script>
    </body>
    </html>
    

    不够精确,在计算的时候有些错误。希望同学们能一起解决。谢谢!

    展开全文
  • 自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我一篇关于怎样利用HTML5 Canvas制作游戏的入门教程。花了一点时间考虑怎么着手写这篇文章后,我决定先实现一个我觉得最最简单的游戏,然后...

    这是我翻译自LostDecadeGames主页的一篇文章,原文地址:How To Make A Simple HTML5 Canvas Game

    下面是正文:

    自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML5 Canvas制作游戏的入门教程。花了一点时间考虑怎么着手写这篇文章后,我决定先实现一个我觉得最最简单的游戏,然后一行代码一行代码地进行讲解。

    让我们开始吧,首先看看game.js,当然你也可以先玩玩这个游戏(译注:附件是游戏源码,用浏览器打开其中的index.html就可以玩了,或者也可以到lostdecadegames官网上去玩)。

    附件下载地址:simple_canvas_game



    1. 创建一个Canvas对象

     

        // Create the canvas
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        canvas.width = 512;
        canvas.height = 480;
        document.body.appendChild(canvas);

    我们首先要做的是创建一个canvas对象。可以用JavaScript或HTML来做,都非常简单。此处我用的是JS。当创建了canvas之后,我们就可以获取它的上下文对象(context)、设置尺寸,并且把它加到当前文档中。

    2. 载入图片

        // Background image
        var bgReady = false;
        var bgImage = new Image();
        bgImage.onload = function () {
            bgReady = true;
        };
        bgImage.src = "images/background.png";

    游戏需要图像,所以让我们载入一些图片吧。我想尽量简单化,所以只用了Image对象来做,当然,还可以将载入图像的功能封装成一个类或别的任何形式。代 码中的bgReady用来标识图片是否已完全载入,只有当图片载入完成后,我们才能使用它,如果在载入完成前就对其进行绘制或渲染,JS将会报一个DOM error的错误。

    我们会用到三张图片(背景、英雄、怪物),每张图片都需要这样处理。

    3. 定义游戏要使用的对象

        // Game objects
        var hero = {
            speed: 256, // movement in pixels per second
            x: 0,
            y: 0
        };
        var monster = {
            x: 0,
            y: 0
        };
        var monstersCaught = 0;

    定义一些变量,稍后会用到。hero对象的speed属性表示英雄的移动速度(像素/秒);monster对象不会移动,所以仅仅具有一对坐标;monstersCaught表示玩家抓住的怪物数量。

    4. 处理玩家输入

    // Handle keyboard controls
    var keysDown = {};
    addEventListener("keydown", function (e) {
         keysDown[e.keyCode] = true;
    }, false);
    addEventListener("keyup", function (e) {
         delete keysDown[e.keyCode];
    }, false);

    现在进行输入的处理。(对具有web开发背景的人来说,这是目前为止第一个具有挑战性的部分)对一般的网页来说,当用户开始输入时,可能需要马上开始播放 动画或请求数据。但在这里,我们想让游戏逻辑在一个单独的地方对游戏中发生的事情进行处理。为此我们需要将用户输入保存下来以备稍后处理,而不是立即处 理。
    我们通过简单地将事件对应的键编码(keyCode)保存在keysDown变量中来实现。如果该变量中具有某个键编码,就表示用户目前正按下这个键。简单吧!

    5. 新游戏

        // Reset the game when the player catches a monster
        var reset = function () {
             hero.x = canvas.width / 2;
             hero.y = canvas.height / 2;
    
             // Throw the monster somewhere on the screen randomly
             monster.x = 32 + (Math.random() * (canvas.width - 64));
             monster.y = 32 + (Math.random() * (canvas.height - 64));
        };

    通过调用reset函数来开始新游戏。该函数将英雄(即玩家角色)放到屏幕中间,然后随机选择一个位置来安置怪物。

    6. 更新对象

        // Update game objects
        var update = function (modifier) {
            if (38 in keysDown) { // Player holding up
                hero.y -= hero.speed * modifier;
            }
            if (40 in keysDown) { // Player holding down
                hero.y += hero.speed * modifier;
            }
            if (37 in keysDown) { // Player holding left
                hero.x -= hero.speed * modifier;
            }
            if (39 in keysDown) { // Player holding right
                hero.x += hero.speed * modifier;
            }
    
            // Are they touching?
            if (
                hero.x <= (monster.x + 32)
                    && monster.x <= (hero.x + 32)
                    && hero.y <= (monster.y + 32)
                    && monster.y <= (hero.y + 32)
            ) {
                 ++monstersCaught;
                 reset();
            }
        };

    这是update函数,游戏每隔一定时间会调用它一次。它所做的第一件事情是检查用户是否按下了上下左右四个箭头键。如果是,就将我们的英雄向相应的方向移动。

    update有一个modifier参数,这看起来好像有点奇怪。你会在游戏的主函数即main函数中看到它,不过我在这 儿先解释一下。modifier参数是一个从1开始的与时间相关的数。如果间隔刚好为1秒时,它的值就会为1,英雄移动的距离即为256像素(英雄的速度 为256像素/秒);而如果间隔是0.5秒,它的值就为0.5,即英雄移动的距离为其速度的一半,以此类推。通常update函数调用的间隔很短,所以 modifier的值很小,但用这种方式能够确保不管代码执行的速度怎么样,英雄的移动速度都是相同的。

    我们已经实现了根据用户的输入来移动英雄,但我们还可以在移动英雄时对其进行检查,以确定是否有其他事件发生。例如:英雄是否与怪物发生了碰撞——当英雄与怪物发生碰撞时,我们为玩家进行计分(monstersCaught加1)并重置游戏(调用reset函数)。

    7. 渲染对象

        // Draw everything
        var render = function () {
            if (bgReady) {
                 ctx.drawImage(bgImage, 0, 0);
            }
    
            if (heroReady) {
                 ctx.drawImage(heroImage, hero.x, hero.y);
            }
    
            if (monsterReady) {
                 ctx.drawImage(monsterImage, monster.x, monster.y);
            }
    
            // Score
            ctx.fillStyle = "rgb(250, 250, 250)";
            ctx.font = "24px Helvetica";
            ctx.textAlign = "left";
            ctx.textBaseline = "top";
            ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
        };

    当你能够看到你的行动时游戏才会变得更有趣,所以让我们在屏幕上绘制吧。首先我们将背景图片绘制到canvas,然后是英雄和怪物。注意顺序很重要,因为任何位于表层的图片都会将其下面的像素覆盖掉。

    接下来是文字,这有些不同,我们调用fillText函数显示玩家的分数。因为不需要复杂的动画或者对文字进行移动,所以只是绘制一下就ok了。

    8. 游戏主循环

       // The main game loop
        var main = function () {
            var now = Date.now();
            var delta = now - then;
    
            update(delta / 1000);
            render();
    
            then = now;
        };

    游戏的主循环用来控制游戏流程。首先我们要获得当前的时间,这样我们才能计算时间差(自上次循环以来经过的时间)。然后计算modifier的值并交给update(需要将delta除以1000以将其转换为毫秒)。最后调用render并更新记录的时间。

    更多关于游戏循环的内容见“Onslaught! Arena Case Study”。

    9. 开始游戏吧

    // Let's play this game!
    reset();
    var then = Date.now();
    setInterval(main, 1); // Execute as fast as possible

    快完成了,这是最后一段代码。首先调用reset来开始新游戏。(还记得吗,这会将英雄置中并随机安放怪物)。然后将起始时间保存到变量then中并启动游戏的主循环。

    OK!(但愿)你现在已经理解了在HTML5 Canvas中用JS来开发游戏的基础知识了。建议最好是能够自己亲自试一把!

     

    转载于:https://www.cnblogs.com/antineutrino/p/3301880.html

    展开全文
  • 使用Canvas绘图

    2020-07-22 22:18:49
    3、canvas标签习惯上在标签内部对其大小进行设置(其他样式还是该怎样写怎样写还是用css),而不是css js 4、canvas标签本身可以认为是一张普通画板,除此之外没有其他功能,内部的所有内容或者图形要用js脚本
  • html5 canvas写成的水墨大写意画笔

    千次阅读 2016-05-24 21:30:21
    而中国大写意用笔讲究如锥画沙,如屋漏痕,如折叉股,要古朴醇厚,怎样用程序模拟这种变幻多端难以捉摸的笔法效果,一直和围棋一样是个世界难题,但是我们可以用比较简易的办法来大致模拟。 可以笔端落于纸面...
  • canvas画布的使用

    2017-08-29 20:49:20
    canvas画布**上一篇使用画布制作了一个变化的气泡,这篇一下画布怎样使用 1.HTML5的canvas元素使用JavaScript在网页上绘制图像,画布是一个矩形区域,可以控制其每一像素。2.画布默认大小是300*150 不要用css去...
  • 自定义View一直是初中级程序员的痛,在之前也过很多关于自定义控件的文章,很多人也看了一些关于自定义控件的文章或是相关源码,效果不是很好,那么怎样才能学会自定义View呢,我认为基础很重要,先对自定义Vi
  • [quote]Hi,帮我讲解一下WPF怎样Canvas或者Grid上根据变量改变Shape的位置和形状吧~[/quote] 没太理解问题在哪里,不过看样子是数据绑定方面不熟悉? 那就个用到Canvas和数据绑定的例子吧。在VS2008里新建一...
  • 前言:在前面的话 什么是粒子时钟,听上去好高尚的样子。☺。起始也就那样。话不多说,先来张效果图。 感觉是不是还行,怎样做的呢,其实也很简单。再来一张图。 看了这个图片,是不是大致懂了,这个效果是怎么...
  • 本节目标: ...续前节,本节我想看看各种多边形怎样画,于是代码成 var row = 3; var col = 3; for (var m = 1; m ; m++) { for (var n = 1; n ; n++) { setSector(row,col,m,n);
  • 我这次主要是想看看一个多边形要怎样才能被不重不漏的分成若干个三角形, 但这个目标不知道能不能实现。 为了测试,先了以下代码: //解决某个特定问题 function problemSolve(pointArray) { //传入点阵列...
  • 哈哈哈,感觉有点小魔性,给室友说的坚持30s请喝可乐。...每完一个方法就测试一下,虽然可能慢了点,不过总比最后来找bug省事很多。好吧。。我的代码不管怎样。。其实都是一团乱。。。 *{ margin: 0; padding: 0;
  • 本系列文章对应游戏代码已开源 Sinuous game。...在这里打算一个系列教程,讲述怎样从零开始开发一款小游戏。让新者少走弯路,快速入手。也能让自己总结反思,发现问题。 在开始介绍如何游戏前有必要重温一下can...
  • GitHub_ AnJiaoDe/Scale-MasterAPKdemo_ AnJiaoDe/Scale-Master/blob/master/app/build/outputs/apk/app-debug.apk一直好奇酷狗的皮肤预览是怎样实现的。难道是另外了一个一模一样的布局文件,只是宽高不一样?...
  • 1、字符串去重,html... 2、javascript正则表达式之$1...$9 3、jquery插件 ...a href ="javascript:location.href=document.referrer;...5、用webstorm的手机网站 怎样能用手机预览呢? 解决方法:布署到wamp...
  • canvas是H5提供的一个新元素,这个元素的功能真的很强大,一个元素结合JS就可以想绘制什么样的图形就能够出现什么样的图形,是不是也很期待怎样canvas来实现呢?关于canvas元素本身,我想强调是:canvas
  • 后面会用到雷达图,如何下载了 echarts 组件后发现不会动态修改。。之前做小程序一直是 page 里的内容,引入这个组件真的有点懵。...import * as echarts from '../../ec-canvas/echarts';const ap...
  • 上篇文章写道怎么通过 Canvas 识别跳转位置,本篇文章重点介绍怎样使用 adb 命令操作「小人」自己挑动。 adb 是什么 adb 是 Andorid Debug Bridge,可以将安卓手机打开 USB 调试模式,然后连接 USB 线到电脑,就可以...
  • 如何用html5创作一个游戏

    千次阅读 2016-11-18 09:53:25
    自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我一篇关于怎样利用HTML5 Canvas制作游戏的入门教程。花了一点时间考虑怎么着手写这篇文章后,我决定先实现一个我觉得最最简单的游戏,然后...
  • 自定义了一个控件A,我在里面创建了另一个控件B. 请问怎么将B控件绘制出来?? 绘制出来的B控件可不可以触发事件,如果不能怎么添加... [color=red]//这里要怎样写,才能把iv显示出来,并且可以响应事件[/color] } }
  • 注册页面的时候用到了验证码,但不知道怎样实现,所以就在晚上各种搜索,学了简单的一种,在此总结一下。 效果图 总体思路: 使用canvas元素画背景图,用js产生随机验证码,背景颜色以及干扰图线,干扰点,然后...
  • 代码如下, ``` ... ... ... xmlns:local="clr-namespace:WPF4" ...希望能够在运行时,在此界面上使用CTRL+左键 复制一个相同的界面窗口,具有相同功能,C#代码要如何怎样把此xaml文件全转为C#代码?
  • 后来领导说,能不能实现像毛笔那样签名的效果,那好吧,领导说怎样怎样吧,而且我也觉得这里用毛笔效果会更好些。那就只好运用贝塞尔曲线的原理了。实现如下:/** * This view implements the drawing canvas. *...
  • 一个View继承ProgressBar,但是怎样改成竖直的呢,在网上搜了下,有个奇人利用canvas.rotate(-90);canvas.translate(-this.getHeight(), 0);这个方式很创新。拿出来和大家分享下。 package c
  • 自定义竖直ProgressBar

    千次阅读 2012-08-31 17:53:33
    一个View继承ProgressBar,但是怎样改成竖直的呢,在网上搜了下,有个奇人利用canvas.rotate(-90);canvas.translate(-this.getHeight(), 0);这个方式很创新。拿出来和大家分享下。 package com
  • 三角函数之前端动画

    2018-08-21 13:42:00
    但是怎样让动画更顺滑,出更贴近自然的动画,说实话以前我没怎么考虑过。 每次当动效设计师提出,能不能这样那样的时候,我会理所当然地予以否决。所以有很长一段时间,我非常羡慕那些能用 canvas 绘制很酷炫的...

空空如也

空空如也

1 2 3
收藏数 49
精华内容 19
关键字:

怎样写canvas