av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

vue動(dòng)態(tài)渲染svg、添加點(diǎn)擊事件的實(shí)現(xiàn)

瀏覽:29日期:2023-01-31 14:39:23

業(yè)務(wù)需求(vue項(xiàng)目中)

1.頁(yè)面展示svg內(nèi)容2.監(jiān)聽(tīng)svg內(nèi)部的點(diǎn)擊事件3.動(dòng)態(tài)改變svg內(nèi)部元素的屬性和值

html標(biāo)簽

經(jīng)多次實(shí)驗(yàn),用embed、img等標(biāo)簽改變src屬性的方式,均無(wú)法實(shí)現(xiàn)上述全部功能(尤其是svg內(nèi)部點(diǎn)擊事件),最終采用Vue.extend()方法完整實(shí)現(xiàn),代碼也較為簡(jiǎn)潔,html結(jié)構(gòu)如下:

<template> <div> <div id='svgTemplate'></div> </div></template>

直接將svg文件的內(nèi)容復(fù)制粘貼到.vue文件里,是可以在標(biāo)簽內(nèi)直接添加@click事件完成需求的,方式簡(jiǎn)單但會(huì)造成文件過(guò)長(zhǎng),本文不多陳述

實(shí)現(xiàn)思路

1.創(chuàng)建xhr對(duì)象

const xhr = new XMLHttpRequest();this.svgUrl = ...; // svg的絕對(duì)地址,在瀏覽器中打開(kāi)能看到的那個(gè)xhr.open('GET', this.svgUrl, true);xhr.send();

2.監(jiān)聽(tīng)xhr對(duì)象(獲取svg的dom -> 添加事件 -> 修改dom -> 轉(zhuǎn)成虛擬dom并掛載)

xhr.addEventListener('load', () => { // ① 獲取svg的dom const resXML = xhr.responseXML; this.svgDom = resXML.documentElement.cloneNode(true); // console.log(this.svgDom); // ② 添加click事件 let btn = this.svgDom.getElementById('...'); btn.setAttribute('v-on:click', 'this.handleClick()'); // ↑↑↑ 此處注意:原生事件handleClick此時(shí)在window層,解決辦法見(jiàn)后文 // ③ 修改 dom this.svgDom.getElementById('...').childNodes[0].nodeValue = ... this.svgDom.getElementById('...').setAttribute('style', `....; fill:${this.photoResult.resultColor}; ...`); // ↑↑↑ 用js操作dom的語(yǔ)法,動(dòng)態(tài)設(shè)置svg部件的屬性和值 // ④ 將svgDom對(duì)象轉(zhuǎn)換成vue的虛擬dom,創(chuàng)建實(shí)例并掛載到元素上 var oSerializer = new XMLSerializer(); var sXML = oSerializer.serializeToString(this.svgDom); var Profile = Vue.extend({ template: '<div id=’svgTemplate’>' + sXML + '</div>' }); new Profile().$mount('#svgTemplate');});

3.將methods里要執(zhí)行的事件綁定到window下面,供外部(剛添加的 handleClick 事件)調(diào)用

async mounted() { window['handleClick'] = () => { this.takePhoto(); };},methods:{ takePhoto(){ ... }}

到這里就基本完成需求:動(dòng)態(tài)渲染了svg、用js操作dom的語(yǔ)法修改svg部件的屬性和值、給svg部件動(dòng)態(tài)添加了事件 handleClick,最后將 takePhoto() 事件綁定給了 window 對(duì)象的 handleClick,可以放心大膽的在 takePhoto() 里寫(xiě)你要執(zhí)行的內(nèi)容了!

特殊注意

給svg的dom部件添加事件時(shí):1.經(jīng)多次嘗試,只有 setAttribute + v-on:click 寫(xiě)法有效2.setAttribute 不支持 @click(非原生事件),會(huì)報(bào)語(yǔ)法錯(cuò)誤3.addEventListener 和 onclick 均會(huì)被 vue 攔截將svgDom對(duì)象轉(zhuǎn)換成vue的虛擬dom時(shí):1.如果報(bào)錯(cuò)如下

則將 import Vue from 'vue' 改為 import Vue from 'vue/dist/vue.esm.js'其原因及其他解決辦法本文不做探討可自行百度。2.vue.extend() 方法是 vue 的一個(gè)構(gòu)造器,用來(lái)動(dòng)態(tài)創(chuàng)建 vue 實(shí)例,template 組件模板只能有一個(gè)根元素3.$mount 手動(dòng)掛載到 id 為 svgTemplate的 元素上,掛載后將替換原本的dom(替換原本的 <div id='svgTemplate'></div>)。由于每次更新 svg 都要重新掛載,沒(méi)有找到 dom 元素是無(wú)法掛載的,因此 template 里面最外層的 div 也要加上 id 的屬性:

var Profile = Vue.extend({ template: '<div id=’svgTemplate’>' + sXML + '</div>' // ↑↑↑ 最外層的 id 不能省略,否則首次渲染后找不到 #svgTemplate});new Profile().$mount('#svgTemplate'); // ↑↑↑ 原本的 #svgTemplate 將被替換成 Profile 的 template

完整代碼

<template> <div> <div id='svgTemplate'></div> </div></template>

<script>import Vue from 'vue/dist/vue.esm.js';// window.handleClick = () => { // 原本的 handleClick 事件是 window 的// };export default { name: 'svg-drawing', data() { return { /* 全局 */ svgUrl: '', // svg的url svgDom: null, // 獲取到的svg元素 /* svg的變量 */ photoResult: { resultVal: 0, // 測(cè)試結(jié)果 - 值 resultMsg: '未檢測(cè)', // 測(cè)試結(jié)果 - 字段 resultColor: '#dcdee2' // 測(cè)試結(jié)果 - 字段背景色 } }; }, async mounted() { // 將takePhoto方法綁定到window下面,提供給外部調(diào)用 window['handleClick'] = () => { this.takePhoto(); }; }, created() { this.getSvg(); }, methods: { // 初始化svg getSvg() { /* 創(chuàng)建xhr對(duì)象 */ const xhr = new XMLHttpRequest(); this.svgUrl = this.baseUrl + '/svgs/' + 'test.svg'; xhr.open('GET', this.svgUrl, true); xhr.send(); /* 監(jiān)聽(tīng)xhr對(duì)象 */ xhr.addEventListener('load', () => { /* 1. 獲取 dom */ const resXML = xhr.responseXML; this.svgDom = resXML.documentElement.cloneNode(true); /* 2.SVG對(duì)象添加click事件 */ let btnTakePhotoDom = this.svgDom.getElementById('...'); btnTakePhotoDom.setAttribute('v-on:click', 'this.handleClick()'); /* 3. 修改 dom */ this.svgDom.getElementById('...').childNodes[0].nodeValue = ...; this.svgDom.getElementById('...').setAttribute('style', `....; fill:${this.photoResult.resultColor}; ...`); /* 4.將svgDom對(duì)象轉(zhuǎn)換成vue的虛擬dom */ var oSerializer = new XMLSerializer(); var sXML = oSerializer.serializeToString(this.svgDom); var Profile = Vue.extend({ template: '<div id=’svgTemplate’>' + sXML + '</div>' }); // 創(chuàng)建實(shí)例,并掛載到元素上 new Profile().$mount('#svgTemplate'); }); }, // 事件 takePhoto() { ... }, }, beforeDestroy() { this.svgDom = null; }, watch: { photoResult: { handler(newVal, oldVal) { this.getSvg(); }, deep: true } }};</script>

到此這篇關(guān)于vue動(dòng)態(tài)渲染svg、添加點(diǎn)擊事件的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue動(dòng)態(tài)渲染svg、添加點(diǎn)擊事件內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 亚洲三区在线观看 | 天天干天天玩天天操 | 欧美一区二区在线免费观看 | 黄色大片在线免费观看 | 玖玖国产精品视频 | 日本午夜精品一区二区三区 | 中文字幕视频一区 | 青青草视频免费观看 | 一区二区日韩 | 青青草原综合久久大伊人精品 | 日韩视频精品 | 欧美在线成人影院 | 国产日韩欧美在线观看 | 久久精品亚洲欧美日韩久久 | 天天干狠狠操 | 亚洲国产精品99久久久久久久久 | 一级黄色片网址 | 午夜亚洲 | 免费黄色a视频 | 精品久久99 | 日韩成人在线观看 | 亚洲一区二区三区高清 | 久草综合在线 | 欧美成人专区 | 国产一区二区三区免费观看在线 | 国产麻豆一区二区三区 | 欧美日韩不卡 | 色综合久久久久 | 成人精品视频 | 精品九九九 | 久久成人精品 | 国产成人精品一区二区三区网站观看 | 女人一区 | 在线成人一区 | 久久91 | 97精品超碰一区二区三区 | 国产激情一区二区三区 | 欧美精品一区二区三区在线播放 | 亚洲欧美综合精品久久成人 | 国产一区免费视频 | 亚洲一二三区精品 |