vue使用tracking實現(xiàn)人臉識別/人臉偵測完整代碼
1、安裝依賴
npm install tracking.js --save
2、完整代碼(人臉識別功能)
以下代碼實現(xiàn)打開攝像頭識別人臉
注:
1、安卓設(shè)備的人臉識別實現(xiàn)規(guī)則: 打開設(shè)備攝像機后,在相機的拍攝下實時進行人臉識別,如果識別到人臉后,1.5秒后自動拍照(可自行調(diào)整拍照時間)。
2、IOS設(shè)備的人臉識別實現(xiàn)規(guī)則:是利用input file的方式來達到打開IOS設(shè)備攝像機的目的,此時IOS設(shè)備的相機是全屏狀態(tài),所以只能在相機拍攝以后,再利用input的change(changePic)事件來得到拍攝的照片,然后再對照片進行人臉識別(檢測是否存在人臉),如果檢測通過,會保留該圖片并且繪制在頁面上,如果未通過人臉檢測,則會提示未檢測到人臉。
<template>
<div class="camera_outer">
<!--
此處代碼請勿隨意刪除:
input兼容ios無法調(diào)用攝像頭的問題
accept屬性兼容某些華為手機調(diào)用攝像頭,打開的是文件管理器的問題
capture="user" 調(diào)用前置攝像頭 camera 調(diào)用后置攝像頭
如果使用 style="display: none" 隱藏input后,可能會出現(xiàn)無法吊起相冊等問題
-->
<input
type="file"
id="file"
accept="image/*"
capture="user"
style="opacity: 0;"
@change="changePic"
/>
<video
id="videoCamera"
:width="videoWidth"
:height="videoHeight"
autoplay
class="img_bg_camera"
/>
<!--
如果使用 style="display: none" 隱藏canvas后,將不會顯示出人臉檢測的識別框
如需要人臉識別框顯示 video與canvas 樣式是需要相同(目的是保持同一位置)
-->
<canvas
id="canvasCamera"
:width="videoWidth"
:height="videoHeight"
class="img_bg_camera"
/>
<div v-if="imgSrc" class="img_bg_camera" :class="[isDisplay ? 'displayBlock' : 'displayNone']">
<img id="imgId" :src="imgSrc" alt class="tx_img" />
</div>
<div class="bottomButton">
<van-button id="open" type="warning" @click="getCamers()" class="marginRight10" >打開攝像機</van-button>
</div>
</div>
</template>
<script>
// npm install tracking.js --save
require("tracking/build/tracking-min.js");
require("tracking/build/data/face-min.js");
require("tracking/build/data/eye-min.js");
require("tracking/build/data/mouth-min.js");
require("tracking/examples/assets/stats.min.js");
export default {
data() {
return {
videoWidth: 300, //攝像機寬度
videoHeight: 300, //攝像機高度
imgSrc: "", //生成圖片鏈接
canvas: null, //canvas
context: null, //context
video: null, //video
isFlag: false, //非正常拍照
isDisplay: false, //生成的照片是否顯示
}
},
mounted() {
// this.getCompetence();
},
destroyed() {
this.stopNavigator();
},
methods: {
//調(diào)用權(quán)限(打開攝像頭功能)
getCompetence() {
var _this = this;
//得到canvasCamera的元素
this.canvas = document.getElementById("canvasCamera");
this.context = this.canvas.getContext("2d"); // 畫布
this.video = document.getElementById("videoCamera");
// 舊版本瀏覽器可能根本不支持mediaDevices,我們首先設(shè)置一個空對象
if (navigator.mediaDevices === undefined) {
Object.defineProperty(navigator, "mediaDevices", {
value: {},
writable: true,
configurable: true,
enumerable: true,
});
}
// 一些瀏覽器實現(xiàn)了部分mediaDevices,我們不能只分配一個對象,如果使用getUserMedia,因為它會覆蓋現(xiàn)有的屬性。如果缺少getUserMedia屬性,就添加它。
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
// 首先獲取現(xiàn)存的getUserMedia(如果存在)
var getUserMedia = navigator.getUserMedia || navigator.mediaDevices.getUserMedia;
// 有些瀏覽器不支持,會返回錯誤信息
if (!getUserMedia) {
this.$toast("getUserMedia is not implemented in this browser");
return Promise.reject(
new Error(
"getUserMedia is not implemented in this browser"
)
);
}
// 否則,使用Promise將調(diào)用包裝到舊的navigator.getUserMedia
return new Promise(function (resolve, reject) {
getUserMedia.call(
navigator,
constraints,
resolve,
reject
);
});
};
}
var constraints = {
audio: false,
video: {
width: this.videoWidth,
height: this.videoHeight,
transform: "scaleX(-1)",
facingMode: "user", // user 安卓前置攝像頭 {exact: 'environment} 后置攝像頭
},
}
//使蘋果手機和蘋果ipad支持打開攝像機
if (
navigator.userAgent.toLowerCase().indexOf("iphone") != -1 ||
navigator.userAgent.toLowerCase().indexOf("ipad") != -1
) {
//使得file一定可以獲取到
document.getElementById("file").click();
} else { // (安卓/瀏覽器(除safari瀏覽器)) 在用戶允許的情況下,打開相機,得到相關(guān)的流
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
// 舊的瀏覽器可能沒有srcObject
if (!_this.video) {
_this.video = {};
}
try {
_this.video.srcObject = stream;
} catch (err) {
_this.video.src = window.URL.createObjectURL(stream); // window.URL || window.webkitURL
}
_this.isFlag = true;
_this.video.onloadedmetadata = () => {
_this.video.play();
_this.initTracker();// 人臉捕捉
}
})
.catch((err) => {
this.$toast('訪問用戶媒體權(quán)限失敗,請重試');
});
}
},
// 人臉捕捉 設(shè)置各種參數(shù) 實例化人臉捕捉實例對象,注意canvas上面的動畫效果。
// 使用 domId 來控制監(jiān)聽那個容器 Android 使用容器 #videoCamera,IOS使用容器 #imgId
initTracker(domId) {
// this.tracker = new window.tracking.ObjectTracker("face"); // tracker實例
this.tracker = new window.tracking.ObjectTracker(['face', 'eye', 'mouth']); // tracker實例
this.tracker.setInitialScale(4);
this.tracker.setStepSize(2); // 設(shè)置步長
this.tracker.setEdgesDensity(0.1);
try {
this.trackertask = window.tracking.track(domId ? domId :"#videoCamera", this.tracker); // 開始追蹤
} catch (e) {
this.$toast("訪問用戶媒體失敗,請重試")
}
//開始捕捉方法 一直不停的檢測人臉直到檢測到人臉
this.tracker.on("track", (e) => {
//畫布描繪之前清空畫布
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
if (e.data.length === 0) {
if(domId) this.$toast("未檢測到人臉,請重新拍照或上傳")
} else {
if(!domId){ // 安卓設(shè)備
e.data.forEach((rect) => { //設(shè)置canvas 方框的顏色大小
this.context.strokeStyle = "#42e365";
this.context.lineWidth = 2;
this.context.strokeRect(rect.x, rect.y, rect.width, rect.height);
});
if (!this.tipFlag) {
this.$toast("檢測成功,正在拍照,請保持不動2秒")
}
}else{ // IOS設(shè)備或safari瀏覽器
if (!this.tipFlag) {
this.$toast("檢測成功,正在生成,請稍等")
}
}
// 1.5秒后拍照,僅拍一次 給用戶一個準備時間
// falg 限制一直捕捉人臉,只要拍照之后就停止檢測
if (!this.flag) {
this.tipFlag = true
this.flag = true;
this.removePhotoID = setTimeout(() => {
this.$toast("圖像生成中···")
this.setImage(domId ? true:false);
this.stopNavigator() // 關(guān)閉攝像頭
this.flag = false
this.tipFlag = false;
clearInterval(this.removePhotoID)
this.removePhotoID = null
}, 1500);
}
}
});
},
//蘋果手機獲取圖片并且保存圖片
changePic(event) {
this.isDisplay = false; // 隱藏已拍照片的展示
var reader = new FileReader();
var f = (document.getElementById("file")).files;
reader.readAsDataURL(f[0]);
reader.onload = () => {
var re = reader.result;
this.canvasDataURL(re, { quality: 1 }, (base64Codes) => {
if (base64Codes) {
this.imgSrc = base64Codes;
// 此方式是為了檢測圖片中是否有人臉
this.$nextTick(()=>{
this.isFlag = true;
this.initTracker('#imgId')
})
// 如果不需要檢驗拍照或上傳圖片中是否有人臉,可注釋上方人臉檢測代碼,使用此種方式
// this.isDisplay = true;
// this.submitCollectInfo();
} else {
this.$toast('拍照失敗');
}
event.target.value = ""; // 解決上傳相同文件不觸發(fā)change事件問題
});
};
},
//壓縮圖片
canvasDataURL(path, obj, callback) {
let img = new Image();
img.src = path;
const that = this;
img.onload = () => {
// 默認按比例壓縮
var w = that.videoWidth, h = that.videoHeight, scale = w / h;
// 使用人臉識別video高度
// w = obj.width || w;
// h = obj.height || w / scale;
// 使用圖片真實高度(像素)圖像更加清晰
w = img.width;
h = img.height;
var quality = 0.5; // 默認圖片質(zhì)量為0.5
//生成canvas
var canvas = document.createElement("canvas");
// canvas 設(shè)置寬高 使用默認寬高圖片會變形、失真
canvas.width = w
canvas.height = h
var ctx = canvas.getContext("2d");
// 創(chuàng)建屬性節(jié)點
ctx.drawImage(img, 0, 0, w, h);
// 圖像質(zhì)量 數(shù)值范圍(0 ~ 1) 1表示最好品質(zhì),0基本不被辨析但有比較小的文件大小;
if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
quality = obj.quality;
}
// quality值越小,所繪制出的圖像越模糊
var base64 = canvas.toDataURL("image/jpeg", quality);
// 回調(diào)函數(shù)返回base64的值
callback(base64);
};
},
//繪制圖片(拍照功能)
setImage(flag) {
if(!this.context){
this.$toast('請打開攝像機')
return;
}
this.context.drawImage(
flag ? document.getElementById('imgId') : this.video,
0,
0,
this.videoWidth,
this.videoHeight
);
// 獲取圖片base64鏈接
var image = this.canvas.toDataURL("image/png", 0.5);
if (this.isFlag) {
if (image) {
this.imgSrc = image;
this.isDisplay = true;
this.submitCollectInfo();
} else {
this.$toast("圖像生成失敗");
}
} else {
this.$toast("圖像生成失敗");
}
},
//保存圖片
async submitCollectInfo() { //其中可以和后端做一些交互
console.log('與后端交互');
},
// 關(guān)閉攝像頭 并且停止人臉檢測
stopNavigator() {
if (this.video && this.video.srcObject) {
this.video.srcObject.getTracks()[0].stop();
}
if(this.trackertask) this.trackertask.stop();
this.tracker = null;
this.isFlag = false
},
//打開攝像機
getCamers() {
this.isDisplay = false; // 隱藏已拍照片的展示
this.getCompetence();
},
// 以下是提供的幾種可能在優(yōu)化或者與后端交互時需要使用的方法
// //返回
// goBack() {
// this.stopNavigator();
// //可以寫相應(yīng)的返回的一些操作,攜帶一些需要攜帶的參數(shù)
// },
// // 訪問用戶媒體設(shè)備
// getUserMedias(constrains, success, error) {
// if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { //最新標(biāo)準API
// navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
// } else if (navigator && navigator.webkitGetUserMedia) { //webkit內(nèi)核瀏覽器
// navigator.webkitGetUserMedia(constrains).then(success).catch(error);
// } else if (navigator && navigator.mozGetUserMedia) { //Firefox瀏覽器
// navagator.mozGetUserMedia(constrains).then(success).catch(error);
// } else if (navigator && navigator.getUserMedia) { //舊版API
// navigator.getUserMedia(constrains).then(success).catch(error);
// } else {
// this.$toast("你的瀏覽器不支持訪問用戶媒體設(shè)備")
// // error("訪問用戶媒體失敗")
// }
// },
// // Base64轉(zhuǎn)文件
// getBlobBydataURI(dataURI, type) {
// var binary = window.atob(dataURI.split(",")[1]);
// var array = [];
// for (var i = 0; i < binary.length; i++) {
// array.push(binary.charCodeAt(i));
// }
// return new Blob([new Uint8Array(array)], {
// type: type,
// });
// },
// compare(url) {
// let blob = this.getBlobBydataURI(url, 'image/png')
// let formData = new FormData()
// formData.append("file", blob, "file_" + Date.parse(new Date()) + ".png")
// // TODO 得到文件后進行人臉識別
// },
}
}
</script>
<style lang="scss" scoped>
.camera_outer {
position: relative;
overflow: hidden;
background-size: cover;
background: white;
width: 100%;
height: 100%;
}
video,
canvas,
.tx_img {
-moz-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
-ms-transform: scaleX(-1);
-o-transform: scaleX(-1);
transform: scaleX(-1);
}
.img_bg_camera {
position: absolute;
bottom: 25%;
top: 25%;
left: 50%;
margin-left: -150px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
-ms-border-radius: 50%;
-o-border-radius: 50%;
}
.img_bg_camera img {
width: 300px;
height: 300px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
-ms-border-radius: 50%;
-o-border-radius: 50%;
}
.displayNone {
// display: none;
opacity: 0;
}
.displayBlock {
// display: block;
opacity: 1;
}
.marginRight10 {
margin-right: 20px;
}
.bottomButton {
position: fixed;
bottom: 20px;
width: 100%;
text-align: center;
}
</style>該項目在調(diào)試時,tracking.js相關(guān)依賴會在檢測人臉時,會有兩個警告頻繁出現(xiàn),但不會影響項目的運行

第一個問題:[Violation] 'requestAnimationFrame' handler took <N>ms
這個警告通常是因為你的canvas或者video渲染過于復(fù)雜或者數(shù)據(jù)量過大,導(dǎo)致在瀏覽器的一幀內(nèi)渲染超時。但本人目前沒有太好的解決方法,如廣大網(wǎng)友有了解或者是解決辦法,希望可以在評論區(qū)討論一下
第二個問題:Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true.
這個警告大概的意思是 使用getImageData的多次讀回操作會更快,建議將willReadFrequency屬性設(shè)置為true。目前的解決方法是將 node_modules 依賴中的 tracking.js 和 tracking-min.js 這兩個文件中的 getContext("2d") 和 getContext('2d') 整體替換為 getContext("2d",{ willReadFrequently: true })
另外如果不使用npm方式下載,也可以使用本地文件導(dǎo)入的方式 提供tracking.js相關(guān)文件 鏈接: https://pan.baidu.com/s/1JjABqkjgkszBLuJTuzHpvw?pwd=meae 提取碼: meae
3、調(diào)試代碼(無人臉識別,可自行拍照和上傳任意圖片)
<template>
<div class="camera_outer">
<!--
此處代碼請勿隨意刪除:
input兼容ios無法調(diào)用攝像頭的問題
accept屬性兼容某些華為手機調(diào)用攝像頭,打開的是文件管理器的問題
-->
<input
type="file"
id="file"
accept="image/*"
capture="camera"
style="display: none"
@change="changePic"
/>
<video
id="videoCamera"
:width="videoWidth"
:height="videoHeight"
autoplay
class="img_bg_camera"
/>
<canvas
style="display: none"
id="canvasCamera"
:width="videoWidth"
:height="videoHeight"
class="img_bg_camera"
/>
<div
v-if="imgSrc"
class="img_bg_camera"
:class="[isDisplay ? 'displayBlock' : 'displayNone']"
>
<img :src="imgSrc" alt class="tx_img" />
</div>
<div class="bottomButton">
<van-button color="#aaaaaa" @click="stopNavigator()" class="marginRight10"
>關(guān)閉攝像頭</van-button
>
<van-button
id="open"
type="warning"
@click="getCamers()"
class="marginRight10"
>打開攝像機</van-button
>
<van-button type="warning" @click="setImage()">拍照</van-button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
videoWidth: 300, //攝像機寬度
videoHeight: 300, //攝像機高度
imgSrc: "", //生成圖片鏈接
canvas: null, //canvas
context: null, //context
video: null, //video
isFlag: false, //非正常拍照
isDisplay: false, //生成的照片是否顯示
}
},
mounted() {
// this.getCompetence();
},
destroyed() {
this.stopNavigator();
},
methods: {
//調(diào)用權(quán)限(打開攝像頭功能)
getCompetence() {
var _this = this;
//得到canvasCamera的元素
this.canvas = document.getElementById("canvasCamera");
this.context = this.canvas.getContext("2d");
this.video = document.getElementById("videoCamera");
// 舊版本瀏覽器可能根本不支持mediaDevices,我們首先設(shè)置一個空對象
if (navigator.mediaDevices === undefined) {
Object.defineProperty(navigator, "mediaDevices", {
value: {},
writable: true,
configurable: true,
enumerable: true,
});
}
// 一些瀏覽器實現(xiàn)了部分mediaDevices,我們不能只分配一個對象,如果使用getUserMedia,因為它會覆蓋現(xiàn)有的屬性。如果缺少getUserMedia屬性,就添加它。
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
// 首先獲取現(xiàn)存的getUserMedia(如果存在)
var getUserMedia = navigator.getUserMedia || navigator.mediaDevices.getUserMedia;
// 有些瀏覽器不支持,會返回錯誤信息
if (!getUserMedia) {
console.log('getUserMedia is not implemented in this browser');
return Promise.reject(
new Error(
"getUserMedia is not implemented in this browser"
)
);
}
// 否則,使用Promise將調(diào)用包裝到舊的navigator.getUserMedia
return new Promise(function (resolve, reject) {
getUserMedia.call(
navigator,
constraints,
resolve,
reject
);
});
};
}
var constraints = {
audio: false,
video: {
width: this.videoWidth,
height: this.videoHeight,
transform: "scaleX(-1)",
},
}
//使蘋果手機和蘋果ipad支持打開攝像機
if (
navigator.userAgent.toLowerCase().indexOf("iphone") != -1 ||
navigator.userAgent.toLowerCase().indexOf("ipad") != -1
) {
//使得file一定可以獲取到
document.getElementById("file").click();
} else {
//在用戶允許的情況下,打開相機,得到相關(guān)的流
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
// 舊的瀏覽器可能沒有srcObject
if (!_this.video) {
_this.video = {};
}
try {
_this.video.srcObject = stream;
} catch (err) {
_this.video.src = window.URL.createObjectURL(stream);
}
_this.isFlag = true;
_this.video.onloadedmetadata = () => _this.video.play();
})
.catch((err) => {
console.log(err);
});
}
},
//蘋果手機獲取圖片并且保存圖片
changePic() {
var reader = new FileReader();
var f = (document.getElementById("file")).files;
reader.readAsDataURL(f[0]);
reader.onload = () => {
var re = reader.result;
this.canvasDataURL(re, { quality: 0.5 }, (base64Codes) => {
if (base64Codes) {
this.imgSrc = base64Codes;
this.isDisplay = true;
this.submitCollectInfo();
} else {
this.$toast('拍照失敗');
}
});
};
},
//壓縮圖片
canvasDataURL(path, obj, callback) {
let img = new Image();
img.src = path;
const that = this;
img.onload = () => {
// 默認按比例壓縮
var w = that.videoWidth, h = that.videoHeight, scale = w / h;
// w = obj.width || w;
// h = obj.height || w / scale;
w = img.width || w;
h = img.height || w / scale;
var quality = 0.5; // 默認圖片質(zhì)量為0.5
//生成canvas
var canvas = document.createElement("canvas");
// canvas 設(shè)置寬高 使用默認寬高圖片會變形、失真
canvas.width = w
canvas.height = h
var ctx = canvas.getContext("2d");
// 創(chuàng)建屬性節(jié)點
ctx.drawImage(img, 0, 0, w, h);
// 圖像質(zhì)量
if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
quality = obj.quality;
}
// quality值越小,所繪制出的圖像越模糊
var base64 = canvas.toDataURL("image/jpeg", quality);
// 回調(diào)函數(shù)返回base64的值
callback(base64);
};
},
//繪制圖片(拍照功能)
setImage() {
this.context.drawImage(
this.video,
0,
0,
this.videoWidth,
this.videoHeight
);
// 獲取圖片base64鏈接
var image = this.canvas.toDataURL("image/png", 0.5);
if (this.isFlag) {
if (image) {
this.imgSrc = image;
this.isDisplay = true;
this.submitCollectInfo();
} else {
console.log("拍照失敗");
}
} else {
console.log("拍照失敗");
}
},
//保存圖片
async submitCollectInfo() { //其中可以和后端做一些交互
console.log('與后端交互');
},
// 關(guān)閉攝像頭
stopNavigator() {
if (this.video && this.video.srcObject) {
this.video.srcObject.getTracks()[0].stop();
}
},
//打開攝像機
getCamers() {
this.isDisplay = false; // 隱藏已拍照片的展示
this.getCompetence();
},
}
}
</script>
<style lang="scss" scoped>
.camera_outer {
position: relative;
overflow: hidden;
background-size: cover;
background: white;
width: 100%;
height: 100%;
}
video,
canvas,
.tx_img {
-moz-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
-ms-transform: scaleX(-1);
-o-transform: scaleX(-1);
transform: scaleX(-1);
}
.img_bg_camera {
position: absolute;
bottom: 25%;
top: 25%;
left: 50%;
margin-left: -150px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
-ms-border-radius: 50%;
-o-border-radius: 50%;
}
.img_bg_camera img {
width: 300px;
height: 300px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
-ms-border-radius: 50%;
-o-border-radius: 50%;
}
.displayNone {
display: none;
}
.displayBlock {
display: block;
}
.marginRight10 {
margin-right: 20px;
}
.bottomButton {
position: fixed;
bottom: 20px;
width: 100%;
text-align: center;
}
</style>總結(jié)
到此這篇關(guān)于vue使用tracking實現(xiàn)人臉識別/人臉偵測的文章就介紹到這了,更多相關(guān)vue實現(xiàn)人臉識別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
elementui[el-table]toggleRowSelection默認多選事件無法選中問題
這篇文章主要介紹了elementui[el-table]toggleRowSelection默認多選事件無法選中問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
vue中前端如何實現(xiàn)pdf預(yù)覽功能(含vue-pdf插件用法)
這篇文章主要給大家介紹了vue中前端如何實現(xiàn)pdf預(yù)覽功能的相關(guān)資料,文中包含vue-pdf插件用法,在前端開發(fā)中,很多時候我們需要進行pdf文件的預(yù)覽操作,需要的朋友可以參考下2023-07-07
Vue中的assets和static目錄:使用場景及區(qū)別說明
這篇文章主要介紹了Vue中的assets和static目錄:使用場景及區(qū)別說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
vue3+vite引入插件unplugin-auto-import的方法
這篇文章主要介紹了vue3+vite引入插件unplugin-auto-import的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值?,需要的朋友可以參考下2022-10-10
element-plus/element-ui走馬燈配置圖片及圖片自適應(yīng)的最簡便方法
走馬燈功能在展示圖片時經(jīng)常用到,下面這篇文章主要給大家介紹了關(guān)于element-plus/element-ui走馬燈配置圖片及圖片自適應(yīng)的最簡便方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-03-03

