Введение
Модуль скретч-карты должен быть реализован в проекте. Когда проект будет урегулирован после завершения проекта, модуль скретч-карты может быть инкапсулирован. Когда он используется в следующем новом проекте, это может повысить эффективность проекта. , конечно, это также будет более эффективно.Хорошо для использования другими друзьями.
Адрес источника:GitHub.com/Zen G Zoe/vUE…адрес пакета npm:Уууу, эта лошадь plus.com/package/v ue…
Эффект компонента скретч-карты следующий:
Во-вторых, реализация компонента vue скретч-карты.
Реализация функции скретч-карты может быть разделена на три этапа:
1. Построение рабочего процесса
Рабочий процесс используетvue-cliизwebpack-simpleШаблон, может удовлетворить основные компоненты запроса компиляции:
vue init webpack-simple vue-scratch-card
После выполнения введите информацию package.json в соответствии с компонентом.
Use sass? (y/N) y
В проекте здесь я выбираюuse sass.
существуетsrcСоздано в каталогеpackagesкаталог, используемый для хранения всех подкомпонентов, в этом компоненте есть только один компонент скретч-карты, поэтому вpackagesновыйscratch-cardКаталог используется для хранения компонентов наших скретч-карт. Если есть другие подкомпоненты, вы можете продолжитьpackagesДобавьте подкомпоненты, и окончательный каталог выглядит следующим образом:
.
├── README.md
├── index.html
├── node_modules
├── package-lock.json
├── package.json
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── main.js //组合所有子组件,封装组件
│ ├── main.js //入口文件
│ └── packages //用于存放所有的子组件
│ └── scratch-card //用于存放刮刮卡组件
│ └── scratch-card.vue //刮刮卡组件代码
└── webpack.config.js
Для поддержки компонентов вы можете использовать теги<script>Путь введения: упакованные файлы, упакованные в компоненты, должны быть только единообразно упакованы как js:
Итак, нам нужно изменить наш файл конфигурацииwebpack.config.js:
//webpack.config.js
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'vue-scratch-card.js',
library : 'vue-scratch-card', //设置的是使用require时的模块名
libraryTarget : 'umd', //libraryTarget可以设置不同的umd代码,可以是commonjs标准、amd标准,也可以生成通过script标签引入的
umdNamedDefine : true, //会对UMD的构建过程中的amd模块进行命名,否则就用匿名的define
},
При этом для сохранения упакованногоdistкаталог, который должен быть.gitignoreудалено изdistсодержание.
2. Canvas реализует скретч-карту
Скретч-карты в основномCanvasДля достижения, как правило, скретч-карта сочетается с лотереей, тогда нашаDOMДолжен включать дисплей, показывающий результаты лотереиDOM, структура следующая:
//scratch-card.vue
<template>
<div :id='elementId' class='scratchCard'>
<div class="result" v-show='showLucky'>
<slot name='result'></slot>
<img :src="resultImg" alt="" class="pic" />
</div>
<canvas id='scratchCanvas'></canvas>
</div>
</template>
Среди них добавление<slot>Слот, чтобы настроить результат лотереи при вызове этого компонентаDOM.
Далее идет логическая часть, реализующая скретч-карту.
Общая структура js выглядит следующим образом:
//scratch-card.vue
export default {
name : 'vueScratchCard',
data(){
return {
supportTouch : false, //是否支持touch事件
events : [], //touch事件 or mouse事件合集
startMoveHandler : null, //touchstart or mousedown 事件
moveHandler : null, //touchmove or mousemove 事件
endMoveHandler : null, //touchend or mouseend 事件
showLucky : false, //显示隐藏抽奖结果
firstTouch : true, //是否第一次touchstart or mousedown
}
},
props : {
elementId : { //组件最外层DOM的id属性
type : String,
default : 'scratch',
},
moveRadius : { //刮刮范围
type : Number,
default : 15
},
ratio : { //要求刮掉的面积占比,达到这个占比后,将会自动把其余区域清除
type : Number,
default : 0.3
},
startCallback : { //第一次刮回调函数
type : Function,
default : function(){
}
},
clearCallback : { //达到ratio占比后的回调函数
type : Function ,
default : function(){
}
},
coverColor : { //刮刮卡遮罩颜色
type : String,
default : '#C5C5C5'
},
coverImg : { //刮刮卡遮罩图片
type : String,
},
resultImg : { //中奖的图
type : String,
default : 'https://raw.githubusercontent.com/ZENGzoe/imagesCollection/master/2018/default.jpg'
}
},
mounted : function(){
},
methods : {
}
}
Прежде чем вы начнете писать свою логику, вам нужно рассмотреть настраиваемые свойства компонента, добавив вprops, так что использование компонентов может быть более гибким.
Когда компонент смонтирован в экземпляре, начните инициализировать компонент, нарисуйтеCanvas.
//scratch-card.vue
...
mounted : function(){
this.$nextTick(() => {
this.init();
})
},
methods : function(){
init : function(){
if(!this.isSupportCanvas){
alert('当前浏览器不支持canvas');
return;
}
const canvasWrap = document.getElementById(this.elementId);
this.canvas =canvasWrap.querySelector('#scratchCanvas');
this.ctx = this.canvas.getContext('2d');
this.canvas.width = canvasWrap.clientWidth;
this.canvas.height = canvasWrap.clientHeight;
this.createCanvasStyle();
},
createCanvasStyle : function(){
var _this = this;
//当传入coverImg时,优先使用图片,否则使用颜色作为刮刮卡遮罩
if(this.coverImg){
var coverImg = new Image();
coverImg.src = this.coverImg;
coverImg.onload = function(){
_this.ctx.drawImage(coverImg , 0 , 0 , _this.canvas.width , _this.canvas.height);
}
}else{
_this.ctx.fillStyle = _this.coverColor;
_this.ctx.fillRect(0,0,_this.canvas.width , _this.canvas.height);
}
},
}
...
когда необходимоCanvasПри добавлении междоменного изображения вам необходимо преобразовать изображение в base64.
Событие, связанное со страницей ПК,mousesdown,mousemove,mouseup, событие, связанное с мобильной страницей,touchstart,touchmove,touchend, поэтому вам нужно различать привязки событий на разных сторонах.
//scratch-card.vue
...
init : function(){
...
this.bindEvent();
},
bindEvent : function(){
if('ontouchstart' in window) this.supportTouch = true;
this.events = this.supportTouch ? ['touchstart', 'touchmove', 'touchend'] : ['mousedown', 'mousemove', 'mouseup'];
this.addEvent();
},
...
Чтобы уменьшить пространство, привяжите событияaddEventДля конкретной реализации вы можете просмотреть исходный код.
Эффект протирания скретч-картой даетCanvasизglobalCompositeOperationреализация свойства, установкаglobalCompositeOperation = "destination-out"Позвольте вашему пальцу или мыши взаимодействовать сCanvasОбласть перекрытия холста не видна, что позволяет создать эффект скретч-карты. существуетtouchmoveа такжеmousemoveДобавьте эффект очистки к связанному событию. Реализация выглядит следующим образом:
moveEventHandler : function(e){
e.preventDefault();
e = this.supportTouch ? e.touches[0] : e;
const canvasPos = this.canvas.getBoundingClientRect(),
scrollT = document.documentElement.scrollTop || document.body.scrollTop,
scrollL = document.documentElement.scrollLeft || document.body.scrollLeft,
//获取鼠标或手指在canvas画布的位置
mouseX = e.pageX - canvasPos.left - scrollL,
mouseY = e.pageY - canvasPos.top - scrollT;
this.ctx.beginPath();
this.ctx.fillStyle = '#FFFFFF';
this.ctx.globalCompositeOperation = "destination-out";
this.ctx.arc(mouseX, mouseY, this.moveRadius, 0, 2 * Math.PI);
this.ctx.fill();
},
Каждый раз, когда палец или мышь уходят, вычисляется стертая область, и когда стертая область превышает согласованный процент холста, вся стертая область очищается.Canvasхолст. Вычисление стертой области эквивалентно вычислению того, есть ли данные в пикселях на холсте.getImageDataметод для получения пикселей холста. Конкретная реализация выглядит следующим образом:
caleArea : function(){
let pixels = this.ctx.getImageData(0,0,this.canvas.width,this.canvas.height),
transPixels = [];
pixels.data.map((item , i) => {
const pixel = pixels.data[i+3];
if(pixel === 0){
transPixels.push(pixel);
}
})
if(transPixels.length / pixels.data.length > this.ratio){
this.ctx.clearRect(0,0,this.canvas.width , this.canvas.height);
this.canvas.removeEventListener(this.events[0],this.startMoveHandler);
this.canvas.removeEventListener(this.events[1] , this.moveHandler , false);
document.removeEventListener(this.events[2] , this.endMoveHandler , false);
this.clearCallback();
}
}
Каждый раз, когда палец или мышь уходит, чтобы не загрязнять события других областей и не занимать контент, связанные события должны быть очищены.
Тогда вся логика скретч-карты здесь реализована, и следующим шагом будет инкапсуляция компонента скретч-карты в плагин.
3. Упакован в виде плагина
Чтобы инкапсулировать компонент Vue в виде плагина, должен быть общедоступныйinstallметод, так что черезVue.use()Вызов плагина. Для получения дополнительной информации см. VUEофициальная документация.
существуетscratch-cardновый в каталогеindex.js, используется для инкапсуляцииscratchCardизinstallметод:
//scratch-card/index.js
import vueScratchCard from './scratch-card'
vueScratchCard.install = Vue => Vue.component(vueScratchCard.name , vueScratchCard);
if(typeof window !== 'undefined' && window.Vue){
window.Vue.use(vueScratchCard);
}
export default vueScratchCard;
Здесь мы упаковали нашу скретч-карту подкомпонента, если есть другие подкомпоненты, вы можете продолжитьpackagesкаталог и, наконец, вsrcновый каталогindex.js, который объединяет все подкомпоненты.
//src/index.js
import VueScratchCard from './packages/scratch-card/index.js';
const install = function(Vue , opts = {}){
Vue.component(VueScratchCard.name , VueScratchCard);
}
//支持使用标签<script>的方式引入
if(typeof window !== 'undefined' && window.Vue){
install(window.Vue);
}
export default {
install ,
VueScratchCard
}
На этом наш компонент завершен.
3. Опубликовать в нпм
Опубликовать вnpmперед этим нужно изменитьpackage.json,настраивать"private":true,иначеnpmОткажется публиковать приватные пакеты. Кроме того, вам нужно добавить файл ввода,"main":"dist/vue-scratch-card.js", можно использовать, когдаrequireилиimportМодули загружаются при упаковке пакетов.
//package.json
"private": false,
"main" : "dist/vue-scratch-card.js",
Процесс выпуска npm выглядит следующим образом:
1. ВnpmЗарегистрировать аккаунт
2. Чтобы войти в npm, вам нужно изменить адрес зеркала на npm
npm login
3. Добавьте информацию о пользователе и введите пароль учетной записи.
npm adduser
4. Опубликовать
npm publish
После успешного выпуска вы можетеnpmПоиск опубликованных пакетов.
В-четвертых, установите и используйте пакет
После этого мы можем установить и использовать его напрямую~~
Установить:
npm install vue-scratch-card0 -S
использовать:
1. Использование по импорту
import ScratchCard from 'vue-scratch-card0'
Vue.use(ScratchCard)
<vue-scratch-card
element-id='scratchWrap'
:ratio=0.5
:move-radius=50
/>
2. Через теги<script>Цитировать
<vue-scratch-card
element-id='scratchWrap'
:ratio=0.5
:move-radius=50
:start-callback=startCallback
:clear-callback=clearCallback
cover-color='#caa'
/>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el : '#app',
data () {
return {
}
},
methods : {
startCallback(){
console.log('抽奖成功!')
},
clearCallback(){
console.log('清除完毕!')
}
}
})
</script>
V. Резюме
При публикации пакета npm он продолжает запрашиватьPackage name too similar to existing packages, но на официальном сайте npm пакет с таким названием не был найден, и в это время он то и дело менялся.package.jsonИмя в , наконец, успешно выпущено, это непросто~_~