欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證

 更新時(shí)間:2022年03月02日 15:50:54   作者:陽光下的雨u  
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了vue實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證的具體代碼,供大家參考,具體內(nèi)容如下

效果圖:

1、引用自定義組件

import img0 from '../assets/img.jpg';
import img1 from '../assets/img1.jpg';
import img2 from '../assets/img2.jpg';
import img3 from '../assets/img3.jpg';
import img4 from '../assets/img4.jpg';
import img5 from '../assets/img5.jpg';
import solide from "../conponents/phptoSlide"
components: {
? ? solide
? },

2、使用

<solide ref="slideblock" @success="onSuccess" @again="onAgain" @fulfilled="onFulfilled"
? ?@fail="onFail" @refresh="onRefresh" :slider-text="text" :imgs="imgs" :accuracy="accuracy">
? </solide>
??
data () {
? ? return {
? ? ? msg: '',
? ? ? text: '向右滑動(dòng)->',
? ? ? imgs: [
? ? ? ? img0,
? ? ? ? img1,
? ? ? ? img2,
? ? ? ? img3,
? ? ? ? img4,
? ? ? ? img5,
? ? ? ],
? ? ? loginBtn: false,
? ? ? accuracy: 1, // 精確度小,可允許的誤差范圍小;為1時(shí),則表示滑塊要與凹槽完全重疊,才能驗(yàn)證成功。默認(rèn)值為5
? ? ? formLabelAlign: {},
? ? }
?}
? methods: {
? ? onSuccess (times) {
? ? ? // console.log('驗(yàn)證通過');
? ? ? this.loginBtn = true;
? ? ? this.msg = `login success, 耗時(shí)${(times / 1000).toFixed(1)}s`;
? ? },
? ? onFail () {
? ? ? // console.log('驗(yàn)證不通過');
? ? ? this.msg = ''
? ? },
? ? onRefresh () {
? ? ? // console.log('點(diǎn)擊了刷新小圖標(biāo)');
? ? ? this.msg = ''
? ? },
? ? onFulfilled () {
? ? ? // console.log('刷新成功啦!');
? ? },
? ? onAgain () {
? ? ? // console.log('檢測到非人為操作的哦!');
? ? ? this.msg = 'try again';
? ? ? // 刷新
? ? ? this.handleClick();
? ? },
? ? handleClick () {
? ? ? this.$refs.slideblock.reset();
? ? ? this.msg = ''
? ? },
? }

3、自定義組件文件

<template>
? <div class="slide-verify" :style="{width: w + 'px'}" id="slideVerify" onselectstart="return false;">
? ? <!-- 圖片加載遮蔽罩 -->
? ? <div :class="{'slider-verify-loading': loadBlock}"></div>
? ? <canvas :width="w" :height="h" ref="canvas"></canvas>
? ? <div v-if="show" @click="refresh" class="slide-verify-refresh-icon"></div>
? ? <canvas :width="w" :height="h" ref="block" class="slide-verify-block"></canvas>
? ? <!-- container -->
? ? <div class="slide-verify-slider" :class="{'container-active': containerActive, 'container-success': containerSuccess, 'container-fail': containerFail}">
? ? ? <div class="slide-verify-slider-mask" :style="{width: sliderMaskWidth}">
? ? ? ? <!-- slider -->
? ? ? ? <div @mousedown="sliderDown" @touchstart="touchStartEvent" @touchmove="touchMoveEvent" @touchend="touchEndEvent" class="slide-verify-slider-mask-item" :style="{left: sliderLeft}">
? ? ? ? ? <div class="slide-verify-slider-mask-item-icon"></div>
? ? ? ? </div>
? ? ? </div>
? ? ? <span class="slide-verify-slider-text">{{sliderText}}</span>
? ? </div>
? </div>
</template>
<script>
const PI = Math.PI;

function sum (x, y) {
? return x + y
}

function square (x) {
? return x * x
}
export default {
? name: 'SlideVerify',
? props: {
? ? // block length
? ? l: {
? ? ? type: Number,
? ? ? default: 30,
? ? },
? ? // block radius
? ? r: {
? ? ? type: Number,
? ? ? default: 6,
? ? },
? ? // canvas width
? ? w: {
? ? ? type: Number,
? ? ? default: 270,
? ? },
? ? // canvas height
? ? h: {
? ? ? type: Number,
? ? ? default: 90,
? ? },
? ? sliderText: {
? ? ? type: String,
? ? ? default: 'Slide filled right',
? ? },
? ? accuracy: {
? ? ? type: Number,
? ? ? default: 5, // 若為 -1 則不進(jìn)行機(jī)器判斷
? ? },
? ? show: {
? ? ? type: Boolean,
? ? ? default: true,
? ? },
? ? imgs: {
? ? ? type: Array,
? ? ? default: () => [],
? ? },
? },
? data () {
? ? return {
? ? ? containerActive: false, // container active class
? ? ? containerSuccess: false, // container success class
? ? ? containerFail: false, // container fail class
? ? ? canvasCtx: null,
? ? ? blockCtx: null,
? ? ? block: null,
? ? ? block_x: undefined, // container random position
? ? ? block_y: undefined,
? ? ? L: this.l + this.r * 2 + 3, // block real lenght
? ? ? img: undefined,
? ? ? originX: undefined,
? ? ? originY: undefined,
? ? ? isMouseDown: false,
? ? ? trail: [],
? ? ? sliderLeft: 0, // block right offset
? ? ? sliderMaskWidth: 0, // mask width,
? ? ? success: false, // Bug Fixes 修復(fù)了驗(yàn)證成功后還能滑動(dòng)
? ? ? loadBlock: true, // Features 圖片加載提示,防止圖片沒加載完就開始驗(yàn)證
? ? ? timestamp: null,
? ? }
? },
? mounted () {
? ? this.init()
? },
? methods: {
? ? init () {
? ? ? this.initDom()
? ? ? this.initImg()
? ? ? this.bindEvents()
? ? },
? ? initDom () {
? ? ? this.block = this.$refs.block;
? ? ? this.canvasCtx = this.$refs.canvas.getContext('2d')
? ? ? this.blockCtx = this.block.getContext('2d')
? ? },
? ? initImg () {
? ? ? const img = this.createImg(() => {
? ? ? ? // 圖片加載完關(guān)閉遮蔽罩
? ? ? ? this.loadBlock = false;
? ? ? ? this.drawBlock()
? ? ? ? this.canvasCtx.drawImage(img, 0, 0, this.w, this.h)
? ? ? ? this.blockCtx.drawImage(img, 0, 0, this.w, this.h)
? ? ? ? let {
? ? ? ? ? block_x: x,
? ? ? ? ? block_y: y,
? ? ? ? ? r,
? ? ? ? ? L
? ? ? ? } = this
? ? ? ? let _y = y - r * 2 - 1
? ? ? ? let ImageData = this.blockCtx.getImageData(x, _y, L, L);
? ? ? ? this.block.width = L;
? ? ? ? this.blockCtx.putImageData(ImageData, 0, _y)
? ? ? });
? ? ? this.img = img;
? ? },
? ? drawBlock () {
? ? ? this.block_x = this.getRandomNumberByRange(this.L + 10, this.w - (this.L + 10))
? ? ? this.block_y = this.getRandomNumberByRange(10 + this.r * 2, this.h - (this.L + 10))
? ? ? this.draw(this.canvasCtx, this.block_x, this.block_y, 'fill')
? ? ? this.draw(this.blockCtx, this.block_x, this.block_y, 'clip')
? ? },
? ? draw (ctx, x, y, operation) {
? ? ? let {
? ? ? ? l,
? ? ? ? r
? ? ? } = this;
? ? ? ctx.beginPath()
? ? ? ctx.moveTo(x, y)
? ? ? ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI)
? ? ? ctx.lineTo(x + l, y)
? ? ? ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI)
? ? ? ctx.lineTo(x + l, y + l)
? ? ? ctx.lineTo(x, y + l)
? ? ? ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)
? ? ? ctx.lineTo(x, y)
? ? ? ctx.lineWidth = 2
? ? ? ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'
? ? ? ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'
? ? ? ctx.stroke()
? ? ? ctx[operation]()
? ? ? // Bug Fixes 修復(fù)了火狐和ie顯示問題
? ? ? ctx.globalCompositeOperation = "destination-over"
? ? },
? ? createImg (onload) {
? ? ? const img = document.createElement('img');
? ? ? img.crossOrigin = "Anonymous";
? ? ? img.onload = onload;
? ? ? img.onerror = () => {
? ? ? ? img.src = this.getRandomImg()
? ? ? }
? ? ? img.src = this.getRandomImg()
? ? ? return img;
? ? },
? ? // 隨機(jī)生成img src
? ? getRandomImg () {
? ? ? // return require('../assets/img.jpg')
? ? ? const len = this.imgs.length;
? ? ? return len > 0 ?
? ? ? ? this.imgs[this.getRandomNumberByRange(0, len)] :
? ? ? ? 'https://picsum.photos/300/150/?image=' + this.getRandomNumberByRange(0, 1084);
? ? },
? ? getRandomNumberByRange (start, end) {
? ? ? return Math.round(Math.random() * (end - start) + start)
? ? },
? ? refresh () {
? ? ? this.reset()
? ? ? this.$emit('refresh')
? ? },
? ? sliderDown (event) {
? ? ? if (this.success) return;
? ? ? this.originX = event.clientX;
? ? ? this.originY = event.clientY;
? ? ? this.isMouseDown = true;
? ? ? this.timestamp = + new Date();
? ? },
? ? touchStartEvent (e) {
? ? ? if (this.success) return;
? ? ? this.originX = e.changedTouches[0].pageX;
? ? ? this.originY = e.changedTouches[0].pageY;
? ? ? this.isMouseDown = true;
? ? ? this.timestamp = + new Date();
? ? },
? ? bindEvents () {
? ? ? document.addEventListener('mousemove', (e) => {
? ? ? ? if (!this.isMouseDown) return false;
? ? ? ? const moveX = e.clientX - this.originX;
? ? ? ? const moveY = e.clientY - this.originY;
? ? ? ? if (moveX < 0 || moveX + 38 >= this.w) return false;
? ? ? ? this.sliderLeft = moveX + 'px';
? ? ? ? let blockLeft = (this.w - 40 - 20) / (this.w - 40) * moveX;
? ? ? ? this.block.style.left = blockLeft + 'px';

? ? ? ? this.containerActive = true; // add active
? ? ? ? this.sliderMaskWidth = moveX + 'px';
? ? ? ? this.trail.push(moveY);
? ? ? });
? ? ? document.addEventListener('mouseup', (e) => {
? ? ? ? if (!this.isMouseDown) return false
? ? ? ? this.isMouseDown = false
? ? ? ? if (e.clientX === this.originX) return false;
? ? ? ? this.containerActive = false; // remove active
? ? ? ? this.timestamp = + new Date() - this.timestamp;

? ? ? ? const {
? ? ? ? ? spliced,
? ? ? ? ? TuringTest
? ? ? ? } = this.verify();
? ? ? ? if (spliced) {
? ? ? ? ? if (this.accuracy === -1) {
? ? ? ? ? ? this.containerSuccess = true;
? ? ? ? ? ? this.success = true;
? ? ? ? ? ? this.$emit('success', this.timestamp);
? ? ? ? ? ? return;
? ? ? ? ? }
? ? ? ? ? if (TuringTest) {
? ? ? ? ? ? // succ
? ? ? ? ? ? this.containerSuccess = true;
? ? ? ? ? ? this.success = true;
? ? ? ? ? ? this.$emit('success', this.timestamp)
? ? ? ? ? } else {
? ? ? ? ? ? this.containerFail = true;
? ? ? ? ? ? this.$emit('again')
? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? this.containerFail = true;
? ? ? ? ? this.$emit('fail')
? ? ? ? ? setTimeout(() => {
? ? ? ? ? ? this.reset()
? ? ? ? ? }, 1000)
? ? ? ? }
? ? ? })
? ? },
? ? touchMoveEvent (e) {
? ? ? if (!this.isMouseDown) return false;
? ? ? const moveX = e.changedTouches[0].pageX - this.originX;
? ? ? const moveY = e.changedTouches[0].pageY - this.originY;
? ? ? if (moveX < 0 || moveX + 38 >= this.w) return false;
? ? ? this.sliderLeft = moveX + 'px';
? ? ? let blockLeft = (this.w - 40 - 20) / (this.w - 40) * moveX;
? ? ? this.block.style.left = blockLeft + 'px';

? ? ? this.containerActive = true;
? ? ? this.sliderMaskWidth = moveX + 'px';
? ? ? this.trail.push(moveY);
? ? },
? ? touchEndEvent (e) {
? ? ? if (!this.isMouseDown) return false
? ? ? this.isMouseDown = false
? ? ? if (e.changedTouches[0].pageX === this.originX) return false;
? ? ? this.containerActive = false;
? ? ? this.timestamp = + new Date() - this.timestamp;

? ? ? const {
? ? ? ? spliced,
? ? ? ? TuringTest
? ? ? } = this.verify();
? ? ? if (spliced) {
? ? ? ? if (this.accuracy === -1) {
? ? ? ? ? this.containerSuccess = true;
? ? ? ? ? this.success = true;
? ? ? ? ? this.$emit('success', this.timestamp);
? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (TuringTest) {
? ? ? ? ? // succ
? ? ? ? ? this.containerSuccess = true;
? ? ? ? ? this.success = true;
? ? ? ? ? this.$emit('success', this.timestamp)
? ? ? ? } else {
? ? ? ? ? this.containerFail = true;
? ? ? ? ? this.$emit('again')
? ? ? ? }
? ? ? } else {
? ? ? ? this.containerFail = true;
? ? ? ? this.$emit('fail')
? ? ? ? setTimeout(() => {
? ? ? ? ? this.reset()
? ? ? ? }, 1000)
? ? ? }
? ? },
? ? verify () {
? ? ? const arr = this.trail // drag y move distance
? ? ? const average = arr.reduce(sum) / arr.length // average
? ? ? const deviations = arr.map(x => x - average) // deviation array
? ? ? const stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length) // standard deviation
? ? ? const left = parseInt(this.block.style.left)
? ? ? const accuracy = this.accuracy <= 1 ? 1 : this.accuracy > 10 ? 10 : this.accuracy;
? ? ? return {
? ? ? ? spliced: Math.abs(left - this.block_x) <= accuracy,
? ? ? ? TuringTest: average !== stddev, // equal => not person operate
? ? ? }
? ? },
? ? reset () {
? ? ? this.success = false;
? ? ? this.containerActive = false;
? ? ? this.containerSuccess = false;
? ? ? this.containerFail = false;
? ? ? this.sliderLeft = 0;
? ? ? this.block.style.left = 0;
? ? ? this.sliderMaskWidth = 0;
? ? ? // canvas
? ? ? let {
? ? ? ? w,
? ? ? ? h
? ? ? } = this;
? ? ? this.canvasCtx.clearRect(0, 0, w, h)
? ? ? this.blockCtx.clearRect(0, 0, w, h)
? ? ? this.block.width = w

? ? ? // generate img
? ? ? this.img.src = this.getRandomImg();
? ? ? this.$emit('fulfilled')
? ? },
? }
}
</script>
<style scoped>
.slide-verify {
? position: relative;
}

/* 圖片加載樣式 */
.slider-verify-loading {
? position: absolute;
? top: 0;
? right: 0;
? left: 0;
? bottom: 0;
? background: rgba(255, 255, 255, 0.9);
? z-index: 999;
? animation: loading 1.5s infinite;
}

@keyframes loading {
? 0% {
? ? opacity: 0.7;
? }
? 100% {
? ? opacity: 9;
? }
}

.slide-verify-block {
? position: absolute;
? left: 0;
? top: 0;
}

.slide-verify-refresh-icon {
? position: absolute;
? right: 0;
? top: 0;
? width: 34px;
? height: 34px;
? cursor: pointer;
? background: url("../assets/icon_light.png") 0 -437px;
? background-size: 34px 471px;
}

.slide-verify-slider {
? position: relative;
? text-align: center;
? width: 100%;
? height: 40px;
? line-height: 40px;
? /* margin-top: 15px; */
? background: #f7f9fa;
? color: #45494c;
? border: 1px solid #e4e7eb;
}

.slide-verify-slider-mask {
? position: absolute;
? left: 0;
? top: 0;
? height: 40px;
? border: 0 solid #1991fa;
? background: #d1e9fe;
}

.slide-verify-slider-mask-item {
? position: absolute;
? top: 0;
? left: 0;
? width: 40px;
? height: 40px;
? background: #fff;
? box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
? cursor: pointer;
? transition: background 0.2s linear;
}

.slide-verify-slider-mask-item:hover {
? background: #1991fa;
}

.slide-verify-slider-mask-item:hover .slide-verify-slider-mask-item-icon {
? background-position: 0 -13px;
}

.slide-verify-slider-mask-item-icon {
? position: absolute;
? top: 15px;
? left: 13px;
? width: 14px;
? height: 12px;
? background: url("../assets/icon_light.png") 0 -26px;
? background-size: 34px 471px;
}
.container-active .slide-verify-slider-mask-item {
? height: 38px;
? top: -1px;
? border: 1px solid #1991fa;
}

.container-active .slide-verify-slider-mask {
? height: 38px;
? border-width: 1px;
}

.container-success .slide-verify-slider-mask-item {
? height: 38px;
? top: -1px;
? border: 1px solid #52ccba;
? background-color: #52ccba !important;
}

.container-success .slide-verify-slider-mask {
? height: 38px;
? border: 1px solid #52ccba;
? background-color: #d2f4ef;
}

.container-success .slide-verify-slider-mask-item-icon {
? background-position: 0 0 !important;
}

.container-fail .slide-verify-slider-mask-item {
? height: 38px;
? top: -1px;
? border: 1px solid #f57a7a;
? background-color: #f57a7a !important;
}

.container-fail .slide-verify-slider-mask {
? height: 38px;
? border: 1px solid #f57a7a;
? background-color: #fce1e1;
}

.container-fail .slide-verify-slider-mask-item-icon {
? top: 14px;
? background-position: 0 -82px !important;
}

.container-active .slide-verify-slider-text,
.container-success .slide-verify-slider-text,
.container-fail .slide-verify-slider-text {
? display: none;
}
</style>

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • uniapp引入模塊化js文件和非模塊化js文件的四種方式

    uniapp引入模塊化js文件和非模塊化js文件的四種方式

    這篇文章主要介紹了uniapp引入模塊化js文件和非模塊化js文件的四種方式,本文結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-11-11
  • Vue.directive自定義指令的使用詳解

    Vue.directive自定義指令的使用詳解

    本篇文章主要介紹了Vue.directive自定義指令的使用詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Vue+echart?展示后端獲取的數(shù)據(jù)實(shí)現(xiàn)

    Vue+echart?展示后端獲取的數(shù)據(jù)實(shí)現(xiàn)

    本文主要介紹了Vue+echart?展示后端獲取的數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • vue里input根據(jù)value改變背景色的實(shí)例

    vue里input根據(jù)value改變背景色的實(shí)例

    今天小編就為大家分享一篇vue里input根據(jù)value改變背景色的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • vue3.x使用swiper實(shí)現(xiàn)卡片輪播

    vue3.x使用swiper實(shí)現(xiàn)卡片輪播

    這篇文章主要為大家詳細(xì)介紹了vue3.x使用swiper實(shí)現(xiàn)卡片輪播,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Vue3項(xiàng)目中的hooks的使用教程

    Vue3項(xiàng)目中的hooks的使用教程

    今天我們稍微說一下 vue3 項(xiàng)目中的 hooks 的使用,其實(shí)這個(gè) hooks 呢是和 vue2 當(dāng)中的 mixin 是類似的,學(xué)習(xí)過 vue2 的小伙伴一定對(duì) mixin 一定比較熟悉,快跟隨小編一起來學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 動(dòng)態(tài)Axios的配置步驟詳解

    動(dòng)態(tài)Axios的配置步驟詳解

    這篇文章主要給大家分享介紹了關(guān)于動(dòng)態(tài)Axios的配置步驟,文中通過示例代碼介紹的非常詳細(xì),通過這個(gè)教程大家可以很方便的實(shí)現(xiàn)動(dòng)態(tài)Axios的配置,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • 在vue中使用eslint,配合vscode的操作

    在vue中使用eslint,配合vscode的操作

    這篇文章主要介紹了在vue中使用eslint,配合vscode的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Vue3使用setup監(jiān)聽props實(shí)現(xiàn)方法詳解

    Vue3使用setup監(jiān)聽props實(shí)現(xiàn)方法詳解

    這篇文章主要為大家介紹了Vue3使用setup監(jiān)聽props實(shí)現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • vue使用vue-video-player無法播放本地視頻的問題及解決

    vue使用vue-video-player無法播放本地視頻的問題及解決

    這篇文章主要介紹了vue使用vue-video-player無法播放本地視頻的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評(píng)論