<svg ref="svgref" style="width: 17vw; height: 42vh" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 330 400"> // The focus of viewBox is on this attribute <path ref="svgref1" :d="`M ${p12}C ${cp12} ${cp22} ${p22}`" fill="none" vector-effect="non-scaling-stroke" /> // vector-effect="non-scaling-stroke" This attribute needs to be brought here. The line drawn by your path or the arc label will cause adaptive scaling problems. </svg>
Below is the full code
<svg ref="svgref" style="width: 17vw; height: 42vh" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 330 400"> <path ref="svgref1" :d="`M ${p12}C ${cp12} ${cp22} ${p22}`" fill="none" vector-effect="non-scaling-stroke" /> <foreignObject width="100%" height="100%"> <div id="allmenu"> <div v-for="(item, index) in menulist.slice(0, 8)" :key="index" class="menuitem" @click="changeindex((item.name || item.deptName), item.path)" > <span :type="'left' + (index + 1)" class="itemname" :class="[activeindex === (item.name || item.deptName) ? 'fontcolor' : '']" @click="onSetName(item.name || item.deptName)" v-tooltip.text.ellipsis > {<!-- -->{ item.name || item.deptName }} </span> </div> </div> </foreignObject> </svg>
<script> import {<!-- --> _throttle } from './throttle' export default {<!-- --> name: 'leftFrom', components: {<!-- -->}, props: {<!-- --> // Component width and height width: {<!-- --> type: Number, default: 300 }, height: {<!-- --> type: Number, default: 400 }, towMenuname: {<!-- --> type: String, default: '' }, // Component menu bar menulist: {<!-- --> type: Array, default () {<!-- --> return [ // Menu Item {<!-- --> name: 'Menu one menu one menu one' }, {<!-- --> name: 'Menu two menu two menu two' }, {<!-- --> name: 'Menu three menu three menu three' }, {<!-- --> name: 'menu four menu four menu four' }, {<!-- --> name: 'Menu five menu five menu five' }, {<!-- --> name: 'Menu six menu six menu six' }, {<!-- --> name: 'Menu seven menu seven menu seven' }, {<!-- --> name: 'Menu eight menu eight menu eight' }, {<!-- --> name: 'Menu nine menu nine menu nine' }, {<!-- --> name: 'Menu Eleven' }, {<!-- --> name: 'Menu Twelve' }, {<!-- --> name: 'Menu Thirteen' } ] } } }, data () {<!-- --> return {<!-- --> // The t of each option in the menu is used to find the points corresponding to the three-level Bezier curve. Slowly increasing or decreasing t can achieve animation effects. menuitemt: [], //Menu selected state activeindex: '', // Counter, slowly increases and decreases t according to the number of animation frames each time to implement animation counter: 0, bottom: 4, top: 4 } }, computed: {<!-- --> // Right to left 300 - 70 = 230 // starting point p12: function name () {<!-- --> return [150, -10] // from left to right, top to bottom }, p22: function name () {<!-- --> return [170, 400] //The tail below is from left to right, from top to bottom }, // control points cp12: function name () {<!-- --> return [30, 60] //Middle point, negative numbers go to the left, positive numbers go to the right, from top to bottom }, cp22: function name () {<!-- --> return [70, 400] } }, watch: {<!-- --> menulist: {<!-- --> handler (newName, oldName) {<!-- --> this.init() } }, towMenuname: {<!-- --> handler (newName, oldName) {<!-- --> this.activeindex = newName this.top = 0 this.bottom = this.menulist.length - 8 console.log(this.bottom) } } }, created () {<!-- -->}, async mounted () {<!-- --> //Add wheel event var menu = document.getElementById('menu') // Bind a mouse scroll event to the menu menu.onmousewheel = (event) => {<!-- --> // Determine the direction of the mouse wheel scrolling event = event || window.event // alert(event.wheelDelta); up 120, down -120 if (event.wheelDelta > 0 || event.detail < 0) {<!-- --> // Firefox event.detail scroll up -3 scroll down + 3 //Scroll up and change the menulist array this.up() } else {<!-- --> //Scroll down and change the menulist array this.down() } return false } this.init() }, methods: {<!-- --> onSetName (name) {<!-- --> this.$emit('onDataItemName', name) }, // initialization init () {<!-- --> this.$nextTick(function () {<!-- --> this.elem = document.getElementsByClassName('menuitem') let i //The interval between each menu item in the Bezier curve const menuinterval = 1 / 10 for (i = 0; i <this.menulist.length; i + + ) {<!-- --> // Here t is written hard, and the value of t is between 0-1. If 0 is not included here, there are 9 ts, and there are also nine displayed menus (as many menus as less than 9 are displayed) this.menuitemt[i] = (i + 1) * menuinterval if (!this.elem[i]) return // Operate dom to move to the appropriate position this.elem[i].style.left = -44 + this.threeOrderBezier( this.menuitemt[i], this.p12, this.cp12, this.cp22, this.p22 )[0] + 'px' this.elem[i].style.top = -20+ this.threeOrderBezier( this.menuitemt[i], this.p12, this.cp12, this.cp22, this.p22 )[1] + 'px' } }) }, // Get the position of the cubic Bezier curve threeOrderBezier (t, p1, cp1, cp2, p2) {<!-- --> //The parameters are t, the starting point, the two control points and the end point. var [x1, y1] = p1 var[cx1, cy1] = cp1 var [cx2, cy2] = cp2 var [x2, y2] = p2 var x = x1 * (1 - t) * (1 - t) * (1 - t) + 3 * cx1 * t * (1 - t) * (1 - t) + 3 * cx2 * t * t * (1 - t) + x2*t*t*t var y = y1 * (1 - t) * (1 - t) * (1 - t) + 3 * cy1 * t * (1 - t) * (1 - t) + 3 * cy2 * t * t * (1 - t) + y2*t*t*t return[x, y] }, //Change the menu array to use anti-shake throttling down: _throttle(function (val) {<!-- --> if (this?.menulist.length > 8 & amp; & amp; this?.top > 0) {<!-- --> this.animation({<!-- -->}, 0) console.log('bbb') this.bottom = this.bottom + 1 this.top = this.top - 1 } }), up: _throttle(function (val) {<!-- --> if (this?.menulist.length > 8 & amp; & amp; this?.bottom > 0) {<!-- --> this.animation({<!-- -->}, 1) console.log('aaaa') this.bottom = this.bottom - 1 this.top = this.top + 1 } }), // up() {<!-- --> // this.animation({}, 1) // }, // change selection changeindex (name, route) {<!-- --> this.activeindex = name this.$router.push(route) }, //This method is triggered every time the mouse wheel is pressed animation (args, flag) {<!-- --> function animate (draw, duration, callback) {<!-- --> var start = 0 requestAnimationFrame(function animate (time) {<!-- --> start = start + 1 var timePassed = start if (timePassed > 10) {<!-- --> timePassed = duration } draw(timePassed) if (timePassed < 10) {<!-- --> requestAnimationFrame(animate) } else callback() }) } animate( (timePassed) => {<!-- --> //Call the method that needs to be executed this.counter = this.counter + 1 var i // Divide each interval into 26 parts based on the number of frames const menuinterval = 1 / 10 / 10 var elem = document.getElementsByClassName('menuitem') // if (!elem[i]) return if (flag) {<!-- --> for (i = 0; i < 8; i + + ) {<!-- --> elem[i].style.left = -44 + this.threeOrderBezier( this.menuitemt[i] - menuinterval * this.counter, this.p12, this.cp12, this.cp22, this.p22 )[0] + 'px' elem[i].style.top = -20+ this.threeOrderBezier( this.menuitemt[i] - menuinterval * this.counter, this.p12, this.cp12, this.cp22, this.p22 )[1] + 'px' } } else {<!-- --> for (i = 0; i < 8; i + + ) {<!-- --> elem[i].style.left = -44+ this.threeOrderBezier( this.menuitemt[i] + menuinterval * this.counter, this.p12, this.cp12, this.cp22, this.p22 )[0] + 'px' elem[i].style.top = -20+ this.threeOrderBezier( this.menuitemt[i] + menuinterval * this.counter, this.p12, this.cp12, this.cp22, this.p22 )[1] + 'px' } } // console.log(elem[1].style.left, elem[1].style.top) }, 300, function changeItems () {<!-- --> if (flag) {<!-- --> this.menulist.push(this.menulist.shift()) } else {<!-- --> var last = this.menulist.pop() // Get the last item of the array this.menulist.unshift(last) //Insert the first position in the array } this.init() this.counter = 0 }.bind(this) ) } } } </script>