zoukankan      html  css  js  c++  java
  • (1/2)Canvas的交互&存为图片-基本篇

    前言

    公司的产品同学看到朋友圈疯传的这张图后。一拍脑袋,决定做个H5版本的来推广一波。

    clipboard.png

    需求如下:

    1. 文字变成可以点击的,而且还要能够变色(闪瞎有木有)

    2. 中间的姓名换成用户的微信头像

    3. 点击button后,将canvas的操作结果保存成图片,来现微信长按保存到本地的功能。

    难点总结:

    1. 页面元素canvas基本的api画到画布上(要解决显示自适应的问题);

    2. 如何实现点击canvas,识别点击文字的对应位置;

    3. 图片保存的api;

    canvas的基本绘制和自适应

    代码部分请忽略css样式

    canvas初始化

    html

    <canvas id="test"></canvas>
    var canvas = document.getElementById('test'),
            ctx = canvas.getContext('2d');

    js | canvas自适应方案

    1. 等比公式:设计图元素尺寸/设计图宽度 = 显示图元素尺寸/移动设备像素宽度;

    2. 推导: 显示图元素尺寸 = 设计图元素尺寸*(移动设备像素宽度/设计图宽度);

    3. 定义: rate= 移动设备像素宽度/设计图宽度;

    var width = document.documentElement.clientWidth,
        //自适应比率计算
        rate = (document.documentElement.clientWidth/ 960).toFixed(2),
        height = rate*1540,

    js | canvas面向对象的元素绘制方法

    1. 经由高人指点,将canvas内部的元素记录成一个个记录了颜色大小坐标、等属性的对象。

    2. 这样可以将元素分为几类:简单几何图形(圆,矩形等)、文字、图片这几类;

    3. 同类元素可以用相同的方法绘制(请务必get此技能

    canvas绘制文字

    baseColor = '#000';
    
    //canvas文字对象
     var textArr = [
     {num:0, has_click: 0, worth:750000, x : 60, y : 50+60, fontSize : 25, text : '英雄联盟', color: baseColor,isEn : true },
     {num:1, has_click: 0, worth:750000, x : 310/3, y : 50+650/3, fontSize : 20, text : '守望先锋', color: baseColor }
     ];
    
    //转为自适应文字对象
    var getTextScope = function(textArr){
      var arr = [];
      textArr.forEach(function(item){
        item.x = item.x * rate;
        item.y = item.y * rate;
        item.fontSize = item.fontSize * rate;
        //计算文字对象在canvas中的触摸范围
        item.r = item.x + (item.isEn ? item.text.length / 2 : item.text.length) * item.fontSize;
        item.b = item.y + item.fontSize;
        arr.push(item);
      });
    return arr;
    };
    
    var newArr = getTextScope(textArr);
    
    
    //绘制文字方法
    var fillTextArr = function(el, textArr){
      textArr.forEach(function(item){
        el.font = item.fontSize + 'px Microsoft Yahei Helvetica Neue  Helvetica, STHeiTi, Arial, sans-serif ';
        el.textAlign= 'left';
        el.textBaseline = 'top';
        el.fillStyle = item.color;
        el.fillText(item.text, item.x, item.y);
        //绘制文字的触摸识别范围(调试用)
        el.beginPath();
        el.rect(item.x, item.y, item.r - item.x, item.b - item.y);
        el.stroke();
      });
    };
    
    fillTextArr(canvas,newArr)

    canvas绘制图片

    html
    页面隐藏元素加载canvas所需要用到的img元素,也可以新建img对象来处理。

    <footer class="footer">
      <div class="img-source hide">
        <img src="/images/avater.jpg" alt="" id="avater"/>
        <img src="/images/avater-bg_05.png" alt="" id="avaterBg"/>
        <img src="/images/3.jpg" alt="" id="img3"/>
        <img src="/images/21060715code_img.jpg" alt="" id="code"/>
        <img src="/images/canvas_tag.png" alt="" id="scan"/>
      </div>
    </footer>

    js

    绘制图片的函数

    var drawImages = function(el, arr){
      arr.forEach(function(item){
       el.drawImage(document.getElementById(item.id), item.x * rate, item.y * rate, item.w * rate, item.h * rate);
      });
    };
    
    var avatar = [
            {id : 'avater', x : 106, y : 50+95, w : 340/3, h : 340/3},
            {id : 'avater', x : 106, y : 50+95, w : 340/3, h : 340/3},
            {id : 'avaterBg', x : 100, y : 50+90, w : 375/3, h : 366/3}
        ];
    
    drawImages(ctx, avatar);

    canvas元素点击交互

    js
    item.r、item.b、item.x、item.y在上文var newArr = getTextScope(textArr);中已经获取;

    //判断点击的点是否在范围内
    
    var isInText = function(item, p){
            if(p.x > item.x && p.x < item.r && p.y > item.y && p.y < item.b) {
                return true;
            }else {
                return false;
            }
        };
    //获取元素所在区域范围的函数
    
    var getEventPosition =  function(ev){
            var x, y;
            if (ev.layerX || ev.layerX == 0) {
                x = ev.layerX;
                y = ev.layerY;
            } else if (ev.offsetX || ev.offsetX == 0) { // Opera
                x = ev.offsetX;
                y = ev.offsetY;
            }
            return {x: x, y: y};
        };

    交互事件实例

    canvas.addEventListener('click', function(e){
        //获取点击坐标
        var p = getEventPosition(e);
        
        //遍历欧判断是否点击到某元素
        newArr.forEach(function(item, i){
                //判断是否点击到元素进行分别操作
                if(isInText(item, p)){
                    //点击到某元素的操作
                }
            });
    }, false);

    现在介绍了canvas绘制的基础操作,下一节就会写到项目的实践部分。

  • 相关阅读:
    一个很吊的swing循环生成窗口。
    hbase操作的问题
    hadoop+hbase
    linux故障救援
    管道命令xargs
    hadoop浅尝 hadoop与hbase交互
    linux源代码阅读笔记 free_page_tables()分析
    词法分析器flex的使用
    每天一个Linux命令(1): find
    梯度下降
  • 原文地址:https://www.cnblogs.com/10manongit/p/12935637.html
Copyright © 2011-2022 走看看