>  기사  >  웹 프론트엔드  >  HTML5 Canvas 실용적인 스크래치 효과의 세부정보 예시

HTML5 Canvas 실용적인 스크래치 효과의 세부정보 예시

黄舟
黄舟원래의
2017-03-30 11:15:571769검색

최근에는 HTML5에 대한 모바일 장치의 지원이 향상됨에 따라 자주하는 활동입니다. 저도 최근에 H5 콘텐츠를 읽고 직접 구현했습니다.

1. 효과

2. >원리는 매우 간단합니다. 즉, 스크래치 영역에 두 개의

캔버스

를 추가하는 것입니다. 첫 번째 캔버스는 스크래치 후 내용을 표시하는 데 사용됩니다. > 또는

문자열 , 두 번째 캔버스는 그림이나 단색으로 채울 수 있는 코팅을 표시하는 데 사용됩니다. 두 번째 캔버스는 두 번째 캔버스 를 덮습니다. 하나. 캔버스를 클릭하거나 문지르면(마우스를 클릭하고 드래그) 첫 번째 캔버스에 내용이 보이도록 클릭한 영역을 투명하게 만들어 스크래치 효과를 줍니다. 3. 구현

(1) Lottery 클래스 정의

function Lottery(id, cover, coverType, width, height, drawPercentCallback) {
    this.conId = id;
    this.conNode = document.getElementById(this.conId);
    this.cover = cover || '#CCC';
    this.coverType = coverType || 'color';
    this.background = null;
    this.backCtx = null;
    this.mask = null;
    this.maskCtx = null;
    this.lottery = null;
    this.lotteryType = 'image';
    this.width = width || 300;
    this.height = height || 100;
    this.clientRect = null;
    this.drawPercentCallback = drawPercentCallback;
}

매개변수 설명:

id: 스크래치 컨테이너의 ID

  • cover: 코팅 내용(이미지 주소 또는 색상 값일 수 있음)은 비워둘 수 있으며 기본값은 #ccc

  • coverType: 코팅 유형, 값은 이미지 또는 색상입니다. 비워둘 수 있습니다. 기본값은 색상입니다

  • 너비: 스크래치 영역의 너비, 기본값은 300px, 비워둘 수 있습니다

  • height: 스크래치 영역의 높이, 기본값은 100px, 비어 있을 수 있음

  • drawPercentCallback: 스크래핑된 영역의 백분율 콜백, 비어 있을 수 있음

  • 그런 다음 사용해야 하는 여러 가지도 정의됩니다.

    변수

    :

배경: 첫 번째 캔버스 요소

  • backCtx: 배경 요소의 2D 컨텍스트(컨텍스트)

  • mask: 두 번째 캔버스 요소

  • maskCtx: 마스크 요소의 2D 컨텍스트

  • lottery: 스크래치 후 표시되는 콘텐츠, 이미지 주소 또는 문자열일 수 있음

  • lotteryType: 스크래치 후 표시되는 콘텐츠 유형, 값은 이미지 또는 텍스트이고 그 뒤에는

    Match

  • clientRect: lotterygetBoundingClientRect() 값을 기록하는 데 사용됩니다. 마스크 요소

  • (2) 스크래치 컨테이너에 두 개의 캔버스를 추가하고 2D 컨텍스트

  • this.background = this.background || this.createElement('canvas', {
        style: 'position:absolute;left:0;top:0;'
    });
    this.mask = this.mask || this.createElement('canvas', {
        style: 'position:absolute;left:0;top:0;'
    });
    
    if (!this.conNode.innerHTML.replace(/[\w\W]| /g, '')) {
        this.conNode.appendChild(this.background);
        this.conNode.appendChild(this.mask);
        this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null;
        this.bindEvent();
    }
    
    this.backCtx = this.backCtx || this.background.getContext('2d');
    this.maskCtx = this.maskCtx || this.mask.getContext('2d');
를 가져옵니다. 여기에 사용되며, 추후 소개할

이벤트도 바운드되어 있습니다.

(3) 첫 번째 캔버스 그리기

첫 번째 캔버스는 이미지와 문자열 두 가지 유형으로 구분됩니다. 그림에 대한 캔버스의 이미지를 직접 그려줍니다. 문자열인 경우 먼저 흰색으로 채운 후 상하좌우 중앙에 문자열을 그립니다.

if (this.lotteryType == 'image') {
    var image = new Image(),
        _this = this;
    image.onload = function () {
        _this.width = this.width;
        _this.height = this.height;
        _this.resizeCanvas(_this.background, this.width, this.height);
        _this.backCtx.drawImage(this, 0, 0);
    }
    image.src = this.lottery;
} else if (this.lotteryType == 'text') {
    this.width = this.width;
    this.height = this.height;
    this.resizeCanvas(this.background, this.width, this.height);
    this.backCtx.save();
    this.backCtx.fillStyle = '#FFF';
    this.backCtx.fillRect(0, 0, this.width, this.height);
    this.backCtx.restore();
    this.backCtx.save();
    var fontSize = 30;
    this.backCtx.font = 'Bold ' + fontSize + 'px Arial';
    this.backCtx.textAlign = 'center';
    this.backCtx.fillStyle = '#F60';
    this.backCtx.fillText(this.lottery, this.width / 2, this.height / 2 + fontSize / 2);
    this.backCtx.restore();
}
(4) 두 번째 A 캔버스 그리기두 번째 캔버스도 이미지나 색상으로 채울 수 있습니다.

여기서 난관이 있습니다. 즉, 마우스 클릭 영역을 투명하게 만드는 방법이 뭔가요? 대답은 여기에 있습니다:developer.mozilla.org/en/docs/Web/Guide/HTML/Canvas_tutorial/Compositing

즉, MaskCtx의

을 그릴 것이므로 두 번째를 그립니다. 캔버스의 코드는 다음과 같습니다.

this.resizeCanvas(this.mask, this.width, this.height);
if (this.coverType == 'color') {    
this.maskCtx.fillStyle = this.cover;    
this.maskCtx.fillRect(0, 0, this.width, this.height);    
this.maskCtx.globalCompositeOperation = 'destination-out';
} else if (this.coverType == 'image'){    var image = new Image(),
        _this = this;
    image.onload = function () {
        _this.maskCtx.drawImage(this, 0, 0);
        _this.maskCtx.globalCompositeOperation = 'destination-out';
    }
    image.src = this.cover;
}

여기서 resizeCanvas는 캔버스의 크기를 변경하는 도구 방법입니다. globalCompositeOperation 设置为 destination-out ,详细的用法请参考上面给出的链接。

(5) 이벤트 바인딩

드로잉이 완료된 후 두 번째 캔버스에 이벤트를 바인딩합니다. 여기에는 모바일 장치와 PC-WEB의 두 가지 상황이 있습니다. 모바일 장치에는 touchstart 및 touchmove 이벤트가 있으며 해당 PC-WEB 이벤트는

key

down 및 mousemove 이벤트입니다. 또한 PC-WEB 모드에서는 mouseup 이벤트를 문서에 바인딩해야 합니다. 마우스를 눌렀습니다. 코드는 다음과 같습니다.

bindEvent: function () {
    var _this = this;
    var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
    var clickEvtName = device ? 'touchstart' : 'mousedown';
    var moveEvtName = device? 'touchmove': 'mousemove';
    if (!device) {
        var isMouseDown = false;
        document.addEventListener('mouseup', function(e) {
            isMouseDown = false;
        }, false);
    }
    this.mask.addEventListener(clickEvtName, function (e) {
        isMouseDown = true;
        var docEle = document.documentElement;
        if (!_this.clientRect) {
            _this.clientRect = {
                left: 0,
                top:0
            };
        }
        var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
        var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
        _this.drawPoint(x, y);
    }, false);

    this.mask.addEventListener(moveEvtName, function (e) {
        if (!device && !isMouseDown) {
            return false;
        }
        var docEle = document.documentElement;
        if (!_this.clientRect) {
            _this.clientRect = {
                left: 0,
                top:0
            };
        }
        var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
        var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
        _this.drawPoint(x, y);
    }, false);
}

여기서 이벤트에 마우스 좌표를 꺼내고 drawPoint를 호출하여 그림을 그립니다. 이에 대해서는 아래에서 설명하겠습니다.

(6) 클릭 및 스미어 영역 그리기

여기서 캔버스의 방사형 그라데이션을 사용하여 마우스 포인터에 원을 그립니다. 코드는 다음과 같습니다.

drawPoint: function (x, y) {
    this.maskCtx.beginPath();
    var radgrad = this.maskCtx.createRadialGradient(x, y, 0, x, y, 30);
    radgrad.addColorStop(0, 'rgba(0,0,0,0.6)');
    radgrad.addColorStop(1, 'rgba(255, 255, 255, 0)');
    this.maskCtx.fillStyle = radgrad;
    this.maskCtx.arc(x, y, 30, 0, Math.PI * 2, true);
    this.maskCtx.fill();
    if (this.drawPercentCallback) {
        this.drawPercentCallback.call(null, this.getTransparentPercent(this.maskCtx, this.width, this.height));
    }
}

(7) 번진 부분의 비율

또한 다음 상호작용을 진행하기 전에 사용자가 얼마나 번졌는지 알아야 합니다. 사용자가 80% 번지면 다음 단계가 표시됩니다.

이 비율을 어떻게 계산하나요? 사실 매우 간단합니다. getImageData 메소드를 사용하여 캔버스에 있는 직사각형의 픽셀 데이터를 지정할 수 있습니다. 각 픽셀은 rgba로 표시되고 칠해진 영역은 투명하므로 해당 값만 판단하면 됩니다. 알파 채널이 투명합니까? 코드는 다음과 같습니다.

getTransparentPercent: function(ctx, width, height) {
    var imgData = ctx.getImageData(0, 0, width, height),
        pixles = imgData.data,
        transPixs = [];
    for (var i = 0, j = pixles.length; i < j; i += 4) {
        var a = pixles[i + 3];
        if (a < 128) {
            transPixs.push(i);
        }
    }
    return (transPixs.length / (pixles.length / 4) * 100).toFixed(2);
}

(8) 입구 init

을 호출하고 마지막으로 그리기 및 재설정을 위한 입구를 제공합니다.

init: function (lottery, lotteryType) {
    this.lottery = lottery;
    this.lotteryType = lotteryType || &#39;image&#39;;
    this.drawLottery();
}

이제 모든 키코드에 대한 설명이 끝났습니다.

위 내용은 HTML5 Canvas 실용적인 스크래치 효과의 세부정보 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.