zoukankan      html  css  js  c++  java
  • 开发Canvas 绘画应用(三):实现对照绘画

    需求分析

    在我的毕设中,提出了视图引导的概念,由两部分功能组成:

    (1)可以对照着图片进行绘画,即将图片以半透明的方式呈现在绘图板上,然后用户可以对照着进行绘画;

    (2)可以直接将简笔画图片直接拖拽到画布上进行检索。

    那么,在这里,我们先实现第一种功能——图片对照绘画。最终想要的实现效果是:当点击图片时,图片边框会呈现蓝色,表示选中状态,同时会在画布上以半透明方式呈现该图片,再点击图片,边框和底板图片都消失,即可以切换显示状态。

    a. 点击前:
    点击前

    b. 点击后:
    点击后

    c. 取消点击:
    取消点击

    实现思路

    我们来分析一下,这种半透明底板方式是如何实现的?

    1)首先,需要利用分层来实现图片参照效果:即设置两个 Canvas,上层的 Canvas 仍旧用来绘画,而下层的 Canvas 则作为底板显示图片,这里需要用到 canvas 的绘制图像 API——drawImage()

    context.drawImage(iamge, srcX, srcY, srcWidth, srcHeight, desX, desY, desWidth, desHeight)
    

    2)其次,为了出现半透明的效果,需要设置上层 canvas 的透明度,这里需要用到 canvas 的图片合成,即通过设置 globalAlpha 属性指定所有绘制的透明度。

    两个应用到2D上下文中所有绘制操作的属性:

    • globalAlpha:属于[0, 1],用于指定所有绘制的透明度。
    • globalCompositionOperation:表示后绘制的图形怎样与先绘制的图形结合,其属性值是字符串。

    代码实现

    该阶段我们需要添加2个模块:一个是视图模块(viewer.js),用于放置我们的参照图片(蜜蜂线画图图片);另一个是底板模块(basePlate.js),用于显示底板。

    另外,此处增加的两个 Canvas 其实前期的画板设置是相同的,因此我们将设置单独拎到一个 cvaConfig.js 文件中,以便代码重用,然后 painter.jsbasePlate.js 只要继承 cvaConfig.js 就行了。

    ☞ index.html

    <img src="asset/img/bee.png" class="view">
    
    <canvas class="painter" id="js-painter"></canvas>
    <canvas class="baseplate" id="js-baseplate"></canvas>
    

    ☞ cvaConfig.js

    export default class CvaConfig {
        constructor() {
            this.config = {
                cvaW: 600,
                cvaH: 500,
                cvaBg: '#fff',
                lineWidth: 2,
                lineJoin: 'round',
                strokeStyle: 'red'
            };
        }
    
        // 画板宽高设置
        // 注意此处不能在 css 中设置,像素会失真,会导致不能获取正确的坐标
        setCvaWH() {
            this.cva.setAttribute('width', this.config.cvaW);
            this.cva.setAttribute('height', this.config.cvaH);
    
            return this;
        }
    
        // 画板背景设置
        setCvaBg() {
            this.ctx.fillStyle = this.config.cvaBg;
            this.ctx.fillRect(0, 0, this.config.cvaW, this.config.cvaH);
    
            return this;
        }
    
        // 画笔设置
        setPen() {
            this.ctx.lineWidth = this.config.lineWidth;
            this.ctx.lineJoin = this.config.lineJoin;
            this.ctx.strokeStyle = this.config.strokeStyle;
    
            return this;
        }
    }
    

    ☞ viewer.js

    export default class Viewer {
    constructor(options) {
        this.options = options;
        this.init();
    }
    
    initSelectors() {
        this.view = $('.view');
    
        return this;
    }
    
    initEvents() {
        this.view.on('touchstart', $.proxy(this.touchF, this));
        this.view.on('touchmove', $.proxy(this.touchF, this));
        this.view.on('touchend', $.proxy(this.touchF, this));
    }
    
    touchF(e) {
        e.preventDefault(); // 阻止浏览器默认行为
    
        switch (e.type) {
            case 'touchstart':
    
                break;
            case 'touchmove':
    
                break;
            case 'touchend':
                this.setStyle($(e.target)); // 切换视图显示状态
                this.setBasePlate(e.target); // 切换底板显示状态
    
                break;
        }
    }
    
    /**
     * 切换视图显示状态,表示是否点击
     * @param {[type]} $el 点击的jQuery目标对象
     */
    setStyle($el) {
        $el.toggleClass('blue-border');
    }
    
    /**
     * 通过点击图视图调用basePlate的接口切换底板显示状态
     * @param {[type]} el 点击的原生js目标对象
     */
    setBasePlate(el) {
    
        // 视图选中时传入图片
        if ($(el).hasClass('blue-border')) {
            this.options.setBasePlate(el);
        } else { // 未选中不传图片
            this.options.setBasePlate();
        }
    }
    
    init() {
        this.initSelectors().initEvents();
    }
    

    }

    ☞ basePlate.js

    basePlate 中功能性的只有一个用来设置底板的函数,通过在点击 viewer 时进行调用:

    import CvaConfig from './cvaConfig.js';
    
    export default class basePlate extends CvaConfig {
        constructor() {
            super();
            this.init();
        }
    
        initSelectors() {
            this.cva = document.getElementById('js-baseplate');
            this.ctx = this.cva.getContext('2d');
    
            return this;
        }
    
        // 设置底板
        setBasePlate(image) {
            if (image) { // 如果有图片,在底板上显示图片
                this.ctx.drawImage(image, 0, 0, this.config.cvaW, this.config.cvaH);
            } else { // 设置空底板
                this.setCvaBg();
            }
        }
    
        init() {
            this.initSelectors();
            this.setCvaWH().setCvaBg();
        }
    }
    

    ☞ painter.js

    painter 中设置其透明度:

    // 设置画布背景及透明度
    _setBg() {
        this.ctx.globalAlpha = 0.7;
        this.setCvaBg();
    
        return this;
    }
    

    OK,参照绘画功能就实现啦,接下去要实现视图引导的第二个功能:通过直接拖拽图片进行检索。当然,我们这里不涉及跟服务端进行交涉,因此只实现前端的拖拽图片功能,这部分会用到一些坐标判断,正好趁此机会好好整理一下。利用拖拽可以实现很多效果,还是挺好玩哒~~加油加油~q(≧▽≦q)

    敬请关注下一篇:开发Canvas 绘画应用(四):实现拖拽绘画

    ✈ Github:paintApp

    ✎ 参考:

    利用分层优化 HTML5 画布渲染


  • 相关阅读:
    OM退货接收设置
    分享一个基于D3.js的互动可重用图表javascript类库 NVD3.js
    免费资源下载:12个漂亮简洁的web背景图案
    分享最新收集的免费photoshop笔刷
    免费素材下载:生态相关的矢量图标集
    分享最新收集的免费photoshop笔刷
    最新的wordpress3.4都有什么新特性
    免费素材下载:学校学院相关图标集
    Adobe开发的基于web的开源代码编辑器 Brackets
    GBin1在线实例帮助你更好的了解jQuery功能特性(三)
  • 原文地址:https://www.cnblogs.com/Ruth92/p/6635823.html
Copyright © 2011-2022 走看看