Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【动效】:刮刮卡

【动效】:刮刮卡

作者头像
WEBJ2EE
发布于 2020-11-05 02:41:59
发布于 2020-11-05 02:41:59
1.3K00
代码可运行
举报
文章被收录于专栏:WebJ2EEWebJ2EE
运行总次数:0
代码可运行

1. 效果展示

2. 技术细节

2.1. Viewport

A viewport represents a polygonal (normally rectangular) area in computer graphics that is currently being viewed. In web browser terms, it refers to the part of the document you're viewing which is currently visible in its window (or the screen, if the document is being viewed in full screen mode). Content outside the viewport is not visible onscreen until scrolled into view.

  • Visual Viewport
    • The portion of the viewport that is currently visible is called the visual viewport. This can be smaller than the layout viewport, such as when the user has pinched-zoomed. The visual viewport is the visual portion of a screen excluding on-screen keyboards, areas outside of a pinch-zoom area, or any other on-screen artifact that doesn't scale with the dimensions of a page.
  • Layout viewport
    • The layout viewport is the viewport into which the browser draws a web page. Essentially, it represents what is available to be seen, while the visual viewport represents what is currently visible on the user's display device.

This becomes important, for example, on mobile devices, where a pinching gesture can usually be used to zoom in and out on a site's contents. The rendered document doesn't change in any way, so the layout viewport remains the same as the user adjusts the zoom level. Instead, the visual viewport is updated to indicate the area of the page that they can see.

2.2. Element.getBoundingClientRect()

The Element.getBoundingClientRect() method returns the size of an element and its position relative to the viewport.

  • The element's size is equal to its width/height + padding + border-width in the case that the standard box model is being used, or width/height only if box-sizing: border-box has been set on it.
  • The result is the smallest rectangle which contains the entire element, with read-only left, top, right, bottom, x, y, width, and height properties describing the overall border-box in pixels. Properties other than width and height are relative to the top-left of the viewport.

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
  <title></title>
  <style type="text/css">
    html,
    body {
      width: 100%;
      height: 100%;
    }

    body {
      margin: 0;
    }

    .box {
      position: absolute;
      left: 300px;
      top: 300px;

      width: 400px;
      height: 200px;
      padding: 20px;
      margin: 100px auto;
      background: purple;
    }
</style>
</head>
<body>
<div class="box"></div>
<div class="result"></div>

<script type="text/javascript">
      let elem = document.querySelector('div.box');
      let rect = elem.getBoundingClientRect();

      const resultDiv = document.querySelector("div.result");
      resultDiv.innerHTML = "";

      for (var key in rect) {
        if(typeof rect[key] !== 'function') {
          let para = document.createElement('div');
          para.textContent  = `${ key } : ${ rect[key] }`;
          resultDiv.appendChild(para);
        }
      }
</script>
</body>
</html>

2.3. Touch

  • Touch Interface
    • The Touch interface represents a single contact point on a touch-sensitive device. The contact point is commonly a finger or stylus and the device may be a touchscreen or trackpad.
  • TouchEvent
    • The TouchEvent interface represents an UIEvent which is sent when the state of contacts with a touch-sensitive surface changes. This surface can be a touch screen or trackpad, for example. The event can describe one or more points of contact with the screen and includes support for detecting movement, addition and removal of contact points, and so forth.
    • Touches are represented by the Touch object; each touch is described by a position, size and shape, amount of pressure, and target element. Lists of touches are represented by TouchList objects.
  • touchmove event
    • Sent when the user moves a touch point along the surface. The event's target is the same element that received the touchstart event corresponding to the touch point, even if the touch point has moved outside that element.

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
  <title></title>
  <style type="text/css">
    #wrapper{
      width: 600px;
      height: 600px;
      margin: 50px auto;
      border: 3px solid blue;
    }

    #viewer{
      position: fixed;
      top: 50%;
      transform: translate(0, -50%);
      border: 1px solid green;
    }
</style>
</head>
<body>
  <div id="wrapper">
  </div>

  <pre id="viewer">
  </pre>

  <script type="text/javascript">
    const ele = document.getElementById("wrapper");
    const viewer = document.getElementById("viewer");
    ele.addEventListener("touchmove", function(e) {
        e.preventDefault();
        var touch = e.targetTouches[0];
        if (touch) {
          viewer.innerHTML = `touchmove:
clientX:${touch.clientX}
clientY:${touch.clientY}`;
        }
    }, false);
</script>
</body>
</html>

2.4. Canvas

2.4.1. 填充图片

CanvasRenderingContext2D.drawImage():

  • The CanvasRenderingContext2D.drawImage() method of the Canvas 2D API provides different ways to draw an image onto the canvas

语法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <canvas id="canvas"></canvas>
  <script type="text/javascript">
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    const image = new Image(60, 45); // Using optional size for image

    image.onload = function(){ // Draw when image has loaded
      // Use the intrinsic size of image in CSS pixels for the canvas element
      canvas.width = this.naturalWidth;
      canvas.height = this.naturalHeight;

      // Will draw the image as 300x227, ignoring the custom size of 60x45
      // given in the constructor
      ctx.drawImage(this, 0, 0);

      // To use the custom size we'll have to specify the scale parameters 
      // using the element's width and height properties - lets draw one 
      // on top in the corner:
      ctx.drawImage(this, 0, 0, this.width, this.height);
    }; 

    // Load an image of intrinsic size 300x227 in CSS pixels
    image.src = 'https://media.prod.mdn.mozit.cloud/attachments/2013/06/22/5397/7a3ec0cae64a95ad454ac3bc2c71c004/rhino.jpg';
</script>
</body>
</html>

2.4.2. 填充文本

CanvasRenderingContext2D.fillText():

  • The CanvasRenderingContext2D method fillText(), part of the Canvas 2D API, draws a text string at the specified coordinates, filling the string's characters with the current fillStyle. An optional parameter allows specifying a maximum width for the rendered text, which the user agent will achieve by condensing the text or by using a lower font size.

语法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CanvasRenderingContext2D.fillText(text, x, y [, maxWidth]);

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <canvas id="canvas" width="400" height="150"></canvas>
  <script type="text/javascript">
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    ctx.font = '50px serif';
    ctx.fillText('Hello world', 50, 60);
    ctx.fillText('Hello world', 50, 120, 140);
</script>
</body>
</html>

2.4.3. 绘制圆弧路径

CanvasRenderingContext2D.arc():

  • The CanvasRenderingContext2D.arc() method of the Canvas 2D API adds a circular arc to the current sub-path.

语法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ctx.arc(x, y, radius, startAngle, endAngle [, anticlockwise]);
  • The rect() method creates a rectangular path whose starting point is at (x, y) and whose size is specified by width and height.

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <canvas id="canvas" width="400" height="150"></canvas>
  <script type="text/javascript">
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    ctx.rect(10, 20, 150, 100);
    ctx.stroke();
</script>
</body>
</html>

2.4.4. 合成操作

CanvasRenderingContext2D.globalCompositeOperation:

  • The CanvasRenderingContext2D.globalCompositeOperation property of the Canvas 2D API sets the type of compositing operation to apply when drawing new shapes.

语法:

3. 综合示例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />  
  <style>
    .bg {
      position: fixed;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      
      background-color: rgba(0, 0, 0, .2);

      display: flex;
      flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .scratch-card{
      width: 2.96rem;
      height: 3.45rem;

      background: url(./red-envelope.png) center center/contain no-repeat;

      position: relative;
    }

    .scratch-card > .scrape-area {
      width: 2.40rem;
      height: 1.20rem;

      position: absolute;
      bottom: 1rem;
      left: 50%;
      transform: translate(-50%, 0);
    }
    
    .scratch-card > .scrape-area > .award {}
    
    .scratch-card > .scrape-area > canvas {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
    }
    .scratch-card > .scrape-area > canvas.finish {
      display: none;
    }

    .scratch-card > .footer {
      position: absolute;
      left: 0;
      bottom: 0;
      
      width: 100%;
    }
</style>
</head>
<body>
  <div class="bg">
    <div class="scratch-card">
      <div class="scrape-area">
        <div class="award">
          <h1>奖品:旋风冲锋</h1>
        </div>
        <canvas id="scrape-canvas"></canvas>
      </div>
      <img class="footer" src="footer.png"/>
    </div>
  </div>
  <script type="text/javascript">
    !function(e, t) {
        var n = t.documentElement,d = e.devicePixelRatio || 1;
        function i() {
            var e = n.clientWidth / 3.75;
            n.style.fontSize = e + "px"
        }
        t.body.style.fontSize = "16px";
        i();
        e.addEventListener("resize", i);
        e.addEventListener("pageshow", function(e) {
              e.persisted && i()
        });
        2 <= d;
    } (window, document)
</script>


  <script>
    function initFestivalCanvas(){
      var remain = 100; // (次)

      const bridge = document.getElementById("scrape-canvas");
      const bridgeCanvas = bridge.getContext('2d');
      
      const img = new Image();
      img.onload = function(){  
        bridgeCanvas.drawImage(img, 0, 0, bridge.width, bridge.height);

        bridgeCanvas.font = "36px bold 微软雅黑";
        bridgeCanvas.fillStyle = "red";
        bridgeCanvas.fillText("刮我一下", 75, 90);
      }
      img.src = './scrape-area-inner.png';

      function detectLeftButton(event) {
          if ('buttons' in event) {
              return event.buttons === 1;
          } else if ('which' in event) {
              return event.which === 1;
          } else {
              return event.button === 1;
          }
      }

      function getBrushPos(xRef, yRef) {
        var bridgeRect = bridge.getBoundingClientRect();
          return {
          x: xRef-bridgeRect.left,
          y: yRef-bridgeRect.top
          };
      }
            
      function drawDot(mouseX,mouseY){
        bridgeCanvas.beginPath();
          bridgeCanvas.arc(mouseX, mouseY, 15, 0, 2*Math.PI, true);
          bridgeCanvas.fillStyle = '#000';
          bridgeCanvas.globalCompositeOperation = "destination-out";
          bridgeCanvas.fill();
      }

      bridge.addEventListener("touchmove", function(e) {
          e.preventDefault();
          const touch = e.targetTouches[0];
          if (touch) {
            const brushPos = getBrushPos(touch.clientX, touch.clientY);
              drawDot(brushPos.x, brushPos.y);     
            if(remain-- < 0){
              const ele = document.getElementById("scrape-canvas");
              ele.className = ele.className + " " + "finish";
            }
          }
      }, false);
    }
    initFestivalCanvas();
</script>
</body>
</html>

参考:

Element.getBoundingClientRect(): https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect Viewport: https://developer.mozilla.org/en-US/docs/Glossary/Viewport https://developer.mozilla.org/en-US/docs/Glossary/visual_viewport https://developer.mozilla.org/en-US/docs/Glossary/Layout_viewport A tale of two viewports: https://www.quirksmode.org/mobile/viewports.html https://www.quirksmode.org/mobile/viewports2.html Touch: https://developer.mozilla.org/en-US/docs/Web/API/Touch https://developer.mozilla.org/zh-CN/docs/Web/API/TouchEvent CanvasRenderingContext2D.arc() https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/arc globalCompositeOperation: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebJ2EE 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
H5 canvas如何载入视频
Canvas可以载入图片,那么Canvas 也可以载入视频。 Canvas加载视频和图片是一样的,使用drawImage,区别就是给一个定 时器不停的抓取每帧的画面,放入Canvas画布里面。 示例1 : 附上demo: <!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=640,user-scalable=0,target-densitydpi=device-dpi"
White feathe
2021/12/08
1K0
H5 canvas如何载入视频
案例效果 | canvas刮刮卡抽奖
案例效果 案例代码 HTML代码 <!DOCTYPE html> <html lang="zh"> <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>刮刮卡抽奖 - 公众号:HTML5 WEB前端分享</title>
HTML5学堂
2021/11/25
2.6K0
案例效果 | canvas刮刮卡抽奖
canvas详细教程! ( 近1万字吐血总结)
今天为大家带来的是我已经写了很久了的canvas详细教程,按照文章的案例一个一个敲下来保证你可以学会绘制很多图案和动画,对入门canvas很有帮助!
用户9999906
2022/12/22
4.2K0
Canvas
http://www.w3c.org/TR/2dcontext/ https://html.spec.whatwg.org/
jinghong
2020/05/09
13.2K0
Canvas
canvas 系列学习笔记四《绘制文本》
CanvasRenderingContext2D.textBaseline 是 Canvas 2D API 描述绘制文本时,当前文本基线的属性。
星宇大前端
2022/09/30
5410
canvas 系列学习笔记四《绘制文本》
HTML5炫酷流星动画特效教程
这是一款HTML5炫酷光粒子动画特效。该特效通过js在页面中生成canvas元素,并通过算法在其中生成炫酷的光粒子动画特效。 使用方法
用户5997198
2019/08/09
10.4K1
HTML5炫酷流星动画特效教程
Canvas 进阶(四)实现一个“刮刮乐”游戏
我们创建一个 ScrapAward 类,通过传入 option 和调用其 restart() 方法实现重新开始。
小皮咖
2019/11/05
1.1K0
【Web技术】929- 前端海报生成的不同方案和优劣
首页测试demo:https://html2canvas.hertzen.com/
pingan8787
2021/04/26
1.5K0
【Web技术】929- 前端海报生成的不同方案和优劣
用 CodeBuddy 打造一张属于她的 520 刮刮乐,程序员的浪漫可以这么强大!
520 马上就要来了,作为一个程序员,除了发红包还能干点啥?你可能会觉得,发个红包是最省事的选择,可是,多少有点“没诚意”的味道。尤其是在这个仪式感爆棚的日子里,直接塞个 1314 元红包过去,虽然看起来挺大气,但终究少了点心思和惊喜。
不惑
2025/05/19
1860
用 CodeBuddy 打造一张属于她的 520 刮刮乐,程序员的浪漫可以这么强大!
一个简单的PHP图片装逼生成原理
一个非常简单的表情生成,省去了配置其他PHP 一个简单的html能能做到 原理非常简单就是利用JS实现 QQ截图20170824093955.png <script type="text/javascript"> function draw(){ var canvas = document.getElementById("myCanvas"); //获取Canvas对象(画布) var write = document.getElementById("text").value /
用户8099761
2023/05/10
4110
canvas 像素操作
在 canvas 中可以使用 context.drawImage(image,dx,dy) 方法将图片绘制在 canvas 上。将图片绘制上去后,还可以使用 context.getImageData(sx, sy, sw, sh) 方法获取 canvas 区域隐含的像素数据,该方法返回一个 ImageData 对象,里面包含的是 canvas 像素信息。
多云转晴
2020/01/14
1.9K0
canvas 像素操作
前端H5生成海报
最近项目需要涉及到前端海报合成分享功能,前端靠不上只能自己上... 现学现卖 相关链接
北溟有鱼QAQ
2022/09/16
5520
【Web技术】774- 基于canvas完成图片裁剪工具
本文是基于canvas去实现图片裁剪工具。因为canvas代码还是比较长的,尽量写思路,完整代码已放在github上。
pingan8787
2020/11/19
1.4K1
【Web技术】774- 基于canvas完成图片裁剪工具
实现Web端自定义截屏
当客户在使用我们的产品过程中,遇到问题需要向我们反馈时,如果用纯文字的形式描述,我们很难懂客户的意思,要是能配上问题截图,这样我们就能很清楚的知道客户的问题了。
神奇的程序员
2021/02/04
2.6K0
canvas学习笔记(八)—- 基本动画
1.用window.setInterVal()、window.setTimeOut()和window.requestAnimationFrame()来定期执行一个指定函数
Java架构师必看
2021/08/19
7140
原 canvas小案例集合(小画板、画的回
作者:汪娇娇 日期:2016.12.8 在现在这个公司呆了4个多月,也是研究了canvas将近4个月,前两周心里就痒痒的想写这方面的博客,但一直没时间。可一直拖着也不是个办法,就这样抽抽空来写吧。 c
jojo
2018/05/03
1.4K1
原                                                                                canvas小案例集合(小画板、画的回
利用canvas阴影功能与双线技巧绘制轨道交通大屏项目效果
近日公司接到一个轨道系统的需求,需要将地铁线路及列车实时位置展示在大屏上。既然是大屏项目,那视觉效果当然是第一重点,咱们可以先来看看项目完成后的效果图。
用户3158888
2020/12/05
5440
canvas 系列学习笔记一《基础》
前端日常图形借助div 等标签组装 + css 样式就满足日常工作需要,对于动画css 和 一些第三方js 库 提供的案例也可以完成。那么为什么要学canvas ?
星宇大前端
2022/06/05
8290
canvas 系列学习笔记一《基础》
前端水印实现方案
为了防止信息泄露或知识产权被侵犯,在web的世界里,对于页面和图片等增加水印处理是十分有必要的,水印的添加根据环境可以分为两大类,前端浏览器环境添加和后端服务环境添加,简单对比一下这两种方式的特点:
落落落洛克
2021/07/05
2.5K0
前端水印实现方案
canvas离屏技术与放大镜实现
利用canvas除了可以实现滤镜,还可以利用离屏技术实现放大镜功能。为了方便讲解,本文分为 2 个应用部分:
心谭博客
2020/04/20
1.4K0
相关推荐
H5 canvas如何载入视频
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验