基于Vue3和Fabric.js實現(xiàn)交互式多邊形繪制功能
需求概述
1.基礎(chǔ)畫布設(shè)置
加載背景圖片
創(chuàng)建與圖片尺寸匹配的Fabric.js畫布
2.多邊形繪制功能
支持固定邊數(shù)多邊形繪制(默認5邊形)
通過點擊添加頂點
限制最大頂點數(shù),達到最大數(shù)后只能閉合
3.視覺反饋系統(tǒng)
繪制頂點可視化(白色圓點,首個點為紅邊框)
點與點之間的連接線(藍色)
實時多邊形預(yù)覽(半透明填充)
4.智能交互
起點閉合檢測(鼠標(biāo)靠近起點時自動吸附)
距離計算(20像素范圍內(nèi)檢測接近)
繪制完成時的狀態(tài)轉(zhuǎn)換
技術(shù)實現(xiàn)詳解
1. 基礎(chǔ)架構(gòu)
項目使用Vue 3的<script setup>
語
import { ref, onMounted, reactive } from 'vue' import { fabric } from 'fabric' import { ElMessage } from 'element-plus'
2. 畫布初始化
在組件掛載時,通過以下步驟初始化畫布:
- 加載背景圖片
- 創(chuàng)建Fabric畫布,尺寸與圖片一致
- 將圖片設(shè)置為背景
onMounted(() => { const imgElement = new Image(); imgElement.src = '/test.jpg'; // 圖片路徑,注意使用公共路徑 src/public/test.jpg imgElement.onload = function() { const imgWidth = imgElement.width; const imgHeight = imgElement.height; const canvas = new fabric.Canvas(canvasRef.value, { width: imgWidth, height: imgHeight }); // 設(shè)置背景圖片 const bgImage = new fabric.Image(imgElement, { scaleX: 1, scaleY: 1, selectable: false, }); canvas.setBackgroundImage(bgImage, canvas.renderAll.bind(canvas)); // 后續(xù)代碼... }; });
3. 多邊形繪制核心邏輯
多邊形繪制實現(xiàn)了以下核心功能:
3.1 狀態(tài)管理
let isDrawing = false; // 繪制狀態(tài) let points = []; // 多邊形頂點 let pointObjects = []; // 頂點可視化對象 let lineObjects = []; // 線段對象 let finalPolygon = null; // 最終多邊形 let activeLine = null; // 當(dāng)前活動線 let activeShape = null; // 動態(tài)多邊形
3.2 頂點可視化
使用Fabric.js的Circle對象實現(xiàn)頂點可視化,保證頂點精確定位:
const createPoint = (x, y, isFirst = false) => { const circle = new fabric.Circle({ radius: 5, fill: 'white', // 白色背景 stroke: isFirst ? 'red' : 'rgb(201, 201, 201)', // 第一個點紅色邊框,其余灰色 strokeWidth: 1, selectable: false, originX: 'center', originY: 'center', left: x, top: y }); canvas.add(circle); return circle; };
注意這里的實現(xiàn)細節(jié):
- 使用originX/originY為'center'確保圓心精確定位在點擊位置
- left/top直接使用點擊坐標(biāo),不再額外減去半徑值
3.3 線段繪制
連接頂點的線段使用Fabric.js的Line對象實現(xiàn):
const createLine = (fromX, fromY, toX, toY) => { const line = new fabric.Line([fromX, fromY, toX, toY], { stroke: 'rgb(51, 164, 255)', strokeWidth: 2, selectable: false }); canvas.add(line); return line; };
3.4 動態(tài)多邊形生成
generatePolygon函數(shù)是實現(xiàn)實時預(yù)覽效果的核心,該函數(shù)會在鼠標(biāo)移動時被調(diào)用,創(chuàng)建從最后一個固定點到當(dāng)前鼠標(biāo)位置的動態(tài)線段和實時更新的多邊形:
const generatePolygon = (mousePointer) => { // 確保處于繪制狀態(tài)且至少有一個點 if (!isDrawing || points.length < 1) return; // 清除舊的活動線 if (activeLine) { canvas.remove(activeLine); activeLine = null; } // 清除舊的活動形狀 if (activeShape) { canvas.remove(activeShape); activeShape = null; } // 創(chuàng)建動態(tài)線段 - 從最后一個點到當(dāng)前鼠標(biāo)位置 const lastPoint = points[points.length - 1]; activeLine = new fabric.Line( [lastPoint.x, lastPoint.y, mousePointer.x, mousePointer.y], { stroke: 'rgb(51, 164, 255)', strokeWidth: 2, selectable: false } ); canvas.add(activeLine); // 如果有至少2個點,創(chuàng)建動態(tài)多邊形 if (points.length >= 2) { // 創(chuàng)建包含所有點和當(dāng)前鼠標(biāo)位置的點數(shù)組 let polygonPoints = [...points]; // 如果鼠標(biāo)接近第一個點,使用第一個點作為閉合點 if (isNearFirstPoint(mousePointer.x, mousePointer.y)) { polygonPoints.push(firstPoint); } else { polygonPoints.push({ x: mousePointer.x, y: mousePointer.y }); } // 創(chuàng)建動態(tài)多邊形 activeShape = new fabric.Polygon( polygonPoints.map(p => ({ x: p.x, y: p.y })), { fill: 'rgb(232, 241, 249)', stroke: 'rgb(232, 241, 249)', strokeWidth: 1, selectable: false, globalCompositeOperation: 'multiply' // 使用混合模式而不是透明度 } ); // 添加到畫布 canvas.add(activeShape); // 確保背景圖在最下層 activeShape.sendToBack(); bgImage.sendToBack(); } canvas.renderAll(); };
動態(tài)多邊形生成技術(shù)細節(jié)分析:
1. 清除歷史狀態(tài): 每次鼠標(biāo)移動時,先清除之前的活動線和活動多邊形,避免重復(fù)渲染
2. 動態(tài)線段創(chuàng)建:
- 使用Fabric.js的Line對象創(chuàng)建從最后固定點到鼠標(biāo)當(dāng)前位置的線段
- 設(shè)置線段顏色為藍色(rgb(51, 164, 255)),提供明顯的視覺反饋
3. 多邊形預(yù)覽生成:
- 當(dāng)已有至少2個點時,創(chuàng)建包含所有固定點和當(dāng)前鼠標(biāo)位置的臨時點數(shù)組
- 通過isNearFirstPoint函數(shù)檢測鼠標(biāo)是否靠近起點,實現(xiàn)"吸附"效果
- 如果鼠標(biāo)接近起點,使用起點坐標(biāo)替代鼠標(biāo)坐標(biāo),視覺上表示可以閉合
4. 多邊形樣式設(shè)置:
- 使用淺藍色填充(rgb(232, 241, 249))和相同顏色的邊框
- 使用globalCompositeOperation: 'multiply'實現(xiàn)半透明效果,使背景圖仍然可見
- 多邊形不可選擇,確保不會干擾繪制流程
5. 層級管理:
- 使用activeShape.sendToBack()確保多邊形在下層
- 使用bgImage.sendToBack()確保背景圖始終在最底層
- 這種層級管理確保了可視化元素的正確疊加順序
4. 事件處理
4.1 鼠標(biāo)點擊事件
鼠標(biāo)點擊事件處理是多邊形繪制的核心邏輯,處理啟動繪制、添加頂點和完成多邊形等關(guān)鍵操作:
canvas.on('mouse:down', function(o) { const pointer = canvas.getPointer(o.e); // 檢查是否點擊在現(xiàn)有對象上 if (o.target && o.target.type === 'polygon' && !isDrawing) { // 如果點擊了現(xiàn)有多邊形且不在繪制模式,只進行選擇 return; } // 如果是第一次點擊,開始繪制 if (!isDrawing) { // 初始化繪制狀態(tài) isDrawing = true; points = []; pointObjects = []; lineObjects = []; // 記錄第一個點 firstPoint = { x: pointer.x, y: pointer.y }; points.push(firstPoint); // 創(chuàng)建第一個點的可視標(biāo)記(紅色表示起點) const firstPointObject = createPoint(pointer.x, pointer.y, true); pointObjects.push(firstPointObject); showMessage(`開始繪制${sidesCount.value}邊形,請繼續(xù)點擊確定頂點位置`, 'info'); } else { console.log('當(dāng)前點數(shù):', points.length, '最大點數(shù):', sidesCount.value); // 檢查是否點擊了第一個點(閉合多邊形) if (isNearFirstPoint(pointer.x, pointer.y)) { // 如果已經(jīng)有至少3個點且點擊接近第一個點,閉合多邊形 if (points.length >= 5) { completePolygon(); } else { showMessage(`需要${sidesCount.value}個點才能閉合多邊形。`, 'warning'); } } else { // 只有在未達到最大點數(shù)時才添加新點 if (points.length < sidesCount.value) { // 繼續(xù)添加點 const newPoint = { x: pointer.x, y: pointer.y }; points.push(newPoint); // 創(chuàng)建點的可視標(biāo)記 const pointObject = createPoint(pointer.x, pointer.y); pointObjects.push(pointObject); // 添加永久連接線 if (points.length >= 2) { const lastIndex = points.length - 1; const line = createLine( points[lastIndex - 1].x, points[lastIndex - 1].y, points[lastIndex].x, points[lastIndex].y ); lineObjects.push(line); } // 如果剛好達到最大點數(shù),提示用戶 if (points.length === sidesCount.value) { showMessage(`已達到最大點數(shù)${sidesCount.value},請點擊第一個點完成繪制`, 'warning'); } } else { // 已達到最大點數(shù),點擊無效,只能點擊起點完成繪制 showMessage(`已達到最大點數(shù)${sidesCount.value},請點擊第一個點完成繪制`, 'warning'); } // 強制更新畫布 canvas.renderAll(); } } });
鼠標(biāo)點擊事件技術(shù)細節(jié)分析:
1. 事件上下文解析:
- 使用canvas.getPointer(o.e)獲取鼠標(biāo)在畫布上的準(zhǔn)確坐標(biāo)
- 通過o.target檢測點擊是否落在現(xiàn)有對象上,防止在已有多邊形上開始新繪制
2. 繪制狀態(tài)初始化:
- 首次點擊時,重置所有狀態(tài)變量(isDrawing, points, pointObjects, lineObjects)
- 創(chuàng)建第一個點并用紅色標(biāo)記,區(qū)別于后續(xù)點
- 通過消息提示告知用戶已開始繪制
3. 多種點擊場景處理:
- 區(qū)分三種主要場景:首次點擊、點擊第一個點(閉合)、添加新點
- 使用狀態(tài)變量isDrawing區(qū)分是否處于繪制模式
4. 閉合多邊形邏輯:
- 使用isNearFirstPoint函數(shù)檢測點擊是否接近起點
- 當(dāng)點擊接近第一個點且已有足夠的點(>=5)時,通過completePolygon()函數(shù)完成多邊形
- 如果點不足,顯示警告消息指導(dǎo)用戶
5. 頂點數(shù)量管理:
- 通過sidesCount.value控制多邊形的最大頂點數(shù)
- 實現(xiàn)嚴(yán)格的頂點數(shù)限制,達到最大數(shù)后只允許閉合操作
- 根據(jù)不同階段提供相應(yīng)的用戶提示
6. 可視化反饋:
- 每個點都有可視化標(biāo)記(白色圓形帶有邊框)
- 點與點之間有顏色鮮明的連接線
- 每次操作后立即更新畫布(canvas.renderAll())
4.2 鼠標(biāo)移動事件
實時更新動態(tài)線段和多邊形形狀:
canvas.on('mouse:move', function(o) { if (!isDrawing) return; const pointer = canvas.getPointer(o.e); generatePolygon(pointer); });
4.3 鍵盤事件
支持Esc鍵取消繪制:
document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && isDrawing) { // 清除所有臨時元素 if (activeLine) { canvas.remove(activeLine); } if (activeShape) { canvas.remove(activeShape); } pointObjects.forEach(point => { if (point) canvas.remove(point); }); lineObjects.forEach(line => { if (line) canvas.remove(line); }); // 重置狀態(tài) points = []; pointObjects = []; lineObjects = []; activeLine = null; activeShape = null; isDrawing = false; firstPoint = null; canvas.renderAll(); showMessage('已取消繪制', 'info'); } });
5. 完成多邊形繪制
當(dāng)用戶點擊接近起點時,多邊形繪制完成:
const completePolygon = () => { if (points.length < 3) { showMessage('至少需要3個點才能形成多邊形', 'warning'); return; } // 清除動態(tài)元素 if (activeLine) { canvas.remove(activeLine); activeLine = null; } // 清除動態(tài)多邊形 if (activeShape) { canvas.remove(activeShape); activeShape = null; } // 移除所有線段 lineObjects.forEach(line => { if (line) canvas.remove(line); }); // 創(chuàng)建最終的多邊形 finalPolygon = new fabric.Polygon(points.map(p => ({ x: p.x, y: p.y })), { fill: 'rgb(227, 242, 202)', stroke: 'rgb(169, 224, 36)', // 線段顏色為rgb(169, 224, 36) strokeWidth: 2, selectable: true, globalCompositeOperation: 'multiply' // 使用混合模式而不是透明度 }); // 移除所有臨時點 pointObjects.forEach(point => { if (point) canvas.remove(point); }); // 添加多邊形到畫布 canvas.add(finalPolygon); canvas.renderAll(); // 重置狀態(tài) points = []; pointObjects = []; lineObjects = []; isDrawing = false; firstPoint = null; showMessage('多邊形繪制完成', 'success'); };
6. 用戶體驗優(yōu)化
6.1 消息提示
使用Element Plus的消息組件提供友好的用戶反饋:
const isNearFirstPoint = (x, y) => { if (!firstPoint) return false; const distance = Math.sqrt( Math.pow(x - firstPoint.x, 2) + Math.pow(y - firstPoint.y, 2) ); return distance < 20; // 20像素范圍內(nèi)視為接近 };
6.2 接近檢測
實現(xiàn)智能的"吸附"功能,方便用戶閉合多邊形:
const isNearFirstPoint = (x, y) => { if (!firstPoint) return false; const distance = Math.sqrt( Math.pow(x - firstPoint.x, 2) + Math.pow(y - firstPoint.y, 2) ); return distance < 20; // 20像素范圍內(nèi)視為接近 };
7. 完整代碼
<template> <div class="canvas-container"> <!-- 使用單獨的canvas元素,圖片將作為背景 --> <canvas ref="canvasRef"></canvas> </div> </template> <script setup> import { ref, onMounted, reactive } from 'vue' import { fabric } from 'fabric' import { ElMessage } from 'element-plus' // 導(dǎo)入Element Plus的消息組件 // 獲取 canvas 元素引用 const canvasRef = ref(null) // 多邊形邊數(shù) const sidesCount = ref(5) // 默認為5邊形 // 顯示提示信息的函數(shù),使用Element Plus const showMessage = (message, type = 'info') => { ElMessage({ message, type, duration: 3000, showClose: true }); } onMounted(() => { // 創(chuàng)建圖片對象 const imgElement = new Image(); imgElement.src = '/test.jpg'; // 圖片路徑,注意使用公共路徑 imgElement.onload = function() { // 獲取圖片寬高 const imgWidth = imgElement.width; const imgHeight = imgElement.height; // 初始化 Fabric 畫布,尺寸與圖片一致 const canvas = new fabric.Canvas(canvasRef.value, { width: imgWidth, height: imgHeight }); // 創(chuàng)建背景圖片 const bgImage = new fabric.Image(imgElement, { scaleX: 1, scaleY: 1, selectable: false, // 設(shè)置背景圖片不可選 }); // 將圖片設(shè)置為背景 canvas.setBackgroundImage(bgImage, canvas.renderAll.bind(canvas)); // 定義變量 let isDrawing = false; // 是否正在繪制多邊形 let points = []; // 存儲多邊形的點 let pointObjects = []; // 存儲點的可視化對象 let lineObjects = []; // 存儲永久線段對象 let finalPolygon = null; // 最終多邊形 let firstPoint = null; // 第一個點(用于閉合多邊形) // 動態(tài)元素 - 隨鼠標(biāo)移動更新 let activeLine = null; // 當(dāng)前鼠標(biāo)位置的活動線 let activeShape = null; // 當(dāng)前動態(tài)多邊形 // 創(chuàng)建點的函數(shù)(用于可視化) const createPoint = (x, y, isFirst = false) => { const circle = new fabric.Circle({ radius: 5, fill: 'white', stroke: isFirst ? 'red' : 'rgb(201, 201, 201)', strokeWidth: 1, selectable: false, originX: 'center', originY: 'center', left: x, top: y }); canvas.add(circle); return circle; }; // 創(chuàng)建連接線的函數(shù) const createLine = (fromX, fromY, toX, toY) => { const line = new fabric.Line([fromX, fromY, toX, toY], { stroke: 'rgb(51, 164, 255)', strokeWidth: 2, selectable: false }); canvas.add(line); return line; }; // 檢查點是否接近第一個點 const isNearFirstPoint = (x, y) => { if (!firstPoint) return false; const distance = Math.sqrt( Math.pow(x - firstPoint.x, 2) + Math.pow(y - firstPoint.y, 2) ); return distance < 20; // 20像素范圍內(nèi)視為接近 }; // 生成或更新動態(tài)多邊形 const generatePolygon = (mousePointer) => { // 確保有足夠的點 if (!isDrawing || points.length < 1) return; // 清除舊的活動線 if (activeLine) { canvas.remove(activeLine); activeLine = null; } // 清除舊的活動形狀 if (activeShape) { canvas.remove(activeShape); activeShape = null; } // 創(chuàng)建動態(tài)線段 - 從最后一個點到當(dāng)前鼠標(biāo)位置 const lastPoint = points[points.length - 1]; activeLine = new fabric.Line( [lastPoint.x, lastPoint.y, mousePointer.x, mousePointer.y], { stroke: 'rgb(51, 164, 255)', strokeWidth: 2, selectable: false } ); canvas.add(activeLine); // 如果有至少2個點,創(chuàng)建動態(tài)多邊形 if (points.length >= 2) { // 創(chuàng)建包含所有點和當(dāng)前鼠標(biāo)位置的點數(shù)組 let polygonPoints = [...points]; // 如果鼠標(biāo)接近第一個點,使用第一個點作為閉合點 if (isNearFirstPoint(mousePointer.x, mousePointer.y)) { polygonPoints.push(firstPoint); } else { polygonPoints.push({ x: mousePointer.x, y: mousePointer.y }); } // 創(chuàng)建動態(tài)多邊形 activeShape = new fabric.Polygon( polygonPoints.map(p => ({ x: p.x, y: p.y })), { fill: 'rgb(232, 241, 249)', stroke: 'rgb(232, 241, 249)', strokeWidth: 1, selectable: false, globalCompositeOperation: 'multiply' // 使用混合模式而不是透明度 } ); // 添加到畫布 canvas.add(activeShape); // 確保背景圖在最下層 activeShape.sendToBack(); bgImage.sendToBack(); } canvas.renderAll(); }; // 完成多邊形繪制 const completePolygon = () => { if (points.length < 3) { showMessage('至少需要3個點才能形成多邊形', 'warning'); return; } // 清除動態(tài)元素 if (activeLine) { canvas.remove(activeLine); activeLine = null; } // 清除動態(tài)多邊形 if (activeShape) { canvas.remove(activeShape); activeShape = null; } // 移除所有線段 lineObjects.forEach(line => { if (line) canvas.remove(line); }); // 創(chuàng)建最終的多邊形 finalPolygon = new fabric.Polygon(points.map(p => ({ x: p.x, y: p.y })), { fill: 'rgb(227, 242, 202)', stroke: 'rgb(169, 224, 36)', // 線段顏色為rgb(169, 224, 36) strokeWidth: 2, selectable: true, globalCompositeOperation: 'multiply' // 使用混合模式而不是透明度 }); // 移除所有臨時點 pointObjects.forEach(point => { if (point) canvas.remove(point); }); // 添加多邊形到畫布 canvas.add(finalPolygon); canvas.renderAll(); // 重置狀態(tài) points = []; pointObjects = []; lineObjects = []; isDrawing = false; firstPoint = null; showMessage('多邊形繪制完成', 'success'); }; // 監(jiān)聽鼠標(biāo)按下事件 canvas.on('mouse:down', function(o) { const pointer = canvas.getPointer(o.e); // 檢查是否點擊在現(xiàn)有對象上 // 注意:這里可能導(dǎo)致問題,因為activeLine和activeShape也是對象 // 只有明確是polygon類型的最終多邊形才應(yīng)該阻止操作 if (o.target && o.target.type === 'polygon' && !isDrawing) { // 如果點擊了現(xiàn)有多邊形且不在繪制模式,只進行選擇 return; } // 如果是第一次點擊,開始繪制 if (!isDrawing) { // 初始化繪制狀態(tài) isDrawing = true; points = []; pointObjects = []; lineObjects = []; // 記錄第一個點 firstPoint = { x: pointer.x, y: pointer.y }; points.push(firstPoint); // 創(chuàng)建第一個點的可視標(biāo)記(紅色表示起點) const firstPointObject = createPoint(pointer.x, pointer.y, true); pointObjects.push(firstPointObject); showMessage(`開始繪制${sidesCount.value}邊形,請繼續(xù)點擊確定頂點位置`, 'info'); } else { console.log('當(dāng)前點數(shù):', points.length, '最大點數(shù):', sidesCount.value); // 檢查是否點擊了第一個點(閉合多邊形) if (isNearFirstPoint(pointer.x, pointer.y)) { // 如果已經(jīng)有至少3個點且點擊接近第一個點,閉合多邊形 if (points.length >= 5) { completePolygon(); } else { showMessage(`需要${sidesCount.value}個點才能閉合多邊形。`, 'warning'); } } else { // 只有在未達到最大點數(shù)時才添加新點 if (points.length < sidesCount.value) { // 繼續(xù)添加點 const newPoint = { x: pointer.x, y: pointer.y }; points.push(newPoint); // 創(chuàng)建點的可視標(biāo)記 const pointObject = createPoint(pointer.x, pointer.y); pointObjects.push(pointObject); // 添加永久連接線 if (points.length >= 2) { const lastIndex = points.length - 1; const line = createLine( points[lastIndex - 1].x, points[lastIndex - 1].y, points[lastIndex].x, points[lastIndex].y ); lineObjects.push(line); } // if (points.length < sidesCount.value) { // showMessage(`已添加${points.length}個點,繼續(xù)點擊添加更多點`, 'info'); // } // 如果剛好達到最大點數(shù),提示用戶 if (points.length === sidesCount.value) { showMessage(`已達到最大點數(shù)${sidesCount.value},請點擊第一個點完成繪制`, 'warning'); } } else { // 已達到最大點數(shù),點擊無效,只能點擊起點完成繪制 showMessage(`已達到最大點數(shù)${sidesCount.value},請點擊第一個點完成繪制`, 'warning'); } // 強制更新畫布 canvas.renderAll(); } } }); // 監(jiān)聽鼠標(biāo)移動事件 canvas.on('mouse:move', function(o) { if (!isDrawing) return; const pointer = canvas.getPointer(o.e); // 生成動態(tài)多邊形 generatePolygon(pointer); }); // 取消繪制的快捷鍵(Esc鍵) document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && isDrawing) { // 清除所有元素 if (activeLine) { canvas.remove(activeLine); } if (activeShape) { canvas.remove(activeShape); } pointObjects.forEach(point => { if (point) canvas.remove(point); }); lineObjects.forEach(line => { if (line) canvas.remove(line); }); // 重置狀態(tài) points = []; pointObjects = []; lineObjects = []; activeLine = null; activeShape = null; isDrawing = false; firstPoint = null; canvas.renderAll(); showMessage('已取消繪制', 'info'); } }); }; }) </script> <style scoped> .canvas-container { display: flex; flex-direction: column; justify-content: center; align-items: center; margin-top: 20px; position: relative; } </style>
以上就是基于Vue3和Fabric.js實現(xiàn)交互式多邊形繪制功能的詳細內(nèi)容,更多關(guān)于Vue3 Fabric.js交互式多邊形繪制的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式
這篇文章主要介紹了vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04詳解Vue CLI 3.0腳手架如何mock數(shù)據(jù)
這篇文章主要介紹了詳解Vue CLI 3.0腳手架如何mock數(shù)據(jù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11詳解Vue的watch中的immediate與watch是什么意思
這篇文章主要介紹了詳解Vue的watch中的immediate與watch是什么意思,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12cesium開發(fā)之如何在vue項目中使用cesium,使用離線地圖資源
這篇文章主要介紹了cesium開發(fā)之如何在vue項目中使用cesium,使用離線地圖資源問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04關(guān)于vue-router路由的傳參方式params query
這篇文章主要介紹了關(guān)于vue-router路由的傳參方式params query,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10vue2老項目中node-sass更換dart-sass的操作方法
這篇文章主要介紹了vue2老項目中node-sass更換dart-sass的操作方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-07-07Vue3中動態(tài)修改樣式與級聯(lián)樣式優(yōu)先順序圖文詳解
在項目中,我們時常會遇到動態(tài)的去綁定操作切換不同的CSS樣式,下面這篇文章主要給大家介紹了關(guān)于Vue3中動態(tài)修改樣式與級聯(lián)樣式優(yōu)先順序的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04