纯 Javascript 或 VueJS 事件的 Mousemove 和 Hover Jquery 效果
Posted
技术标签:
【中文标题】纯 Javascript 或 VueJS 事件的 Mousemove 和 Hover Jquery 效果【英文标题】:Mousemove and Hover Jquery effect to Pure Javascript or VueJS event 【发布时间】:2021-07-17 02:59:49 【问题描述】:我有一个 VueJS 组件,它是美国的 svg 地图图像。我之前使用 jquery 创建悬停效果来显示信息气泡。我正在尝试将其转换为纯 javascript 解决方案。鉴于 vuejs mousemove 似乎不太可靠,因此单击事件似乎是最容易实现的。我在方法中添加了点击事件,我试图捕获 SVG 路径位置并窃取顶部和左侧位置以启用那里的信息框。我试过 this.offsettop 和 this.offsetleft 但它们返回未定义。
我正在尝试转换的 Jquery 代码:
$("path, circle").hover(function(e)
$('#info-box').css('display','block');
$('#info-box').html($(this).data('info'));
);
$("path, circle").mouseleave(function(e)
$('#info-box').css('display','none');
);
$(document).mousemove(function(e)
$('#info-box').css('top',e.pageY-$('#info-box').height()-30);
$('#info-box').css('left',e.pageX-($('#info-box').width())/2);
).mouseover();
var ios = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
if(ios)
$('a').on('click touchend', function()
var link = $(this).attr('href');
window.open(link,'_blank');
return false;
);
VueJS 组件
<template id="geomap-assignments">
<v-card class="pa-4 ma-3 rounded-lg" min->
<div class="card-title-docs">
<h4 class="card-header">Assignments</h4>
<h5 class="card-sub-header"></h5>
</div>
<div class="map-container">
<div id="info-box"></div>
<?xml version="1.0" encoding="utf-8" ?>
<svg xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="us-map" preserveAspectRatio="xMinYMin meet" sodipodi:docname="Republican_Party_presidential_primaries_results,_2016.svg" inkscape:version="0.91 r13725" x="0px" y="0px" viewBox="174 100 959 593" enable-background="new 174 100 959 593" xml:space="preserve">
<sodipodi:namedview bordercolor="#666666" objecttolerance="10" pagecolor="#ffffff" borderopacity="1" gridtolerance="10" guidetolerance="10" inkscape:cx="509.19152" inkscape:cy="282.2353" inkscape:zoom="1.2137643" showgrid="false" id="namedview71" inkscape:current-layer="g5" inkscape:window-maximized="1" inkscape:window-y="-8" inkscape:window-x="-8" inkscape:pageopacity="0" inkscape:window- inkscape:window- inkscape:pageshadow="2">
</sodipodi:namedview>
<g id="g5">
<path id="HI" data-info="<div>State: Hawaii</div><div>Capital: Honolulu</div>" fill="#D3D3D3" d="M407.1,619.3l1.9-3.6l2.3-0.3l0.3,0.8l-2.1,3.1H407.1z M417.3,615.6l6.1,2.6l2.1-0.3l1.6-3.9 l-0.6-3.4l-4.2-0.5l-4,1.8L417.3,615.6z M448,625.6l3.7,5.5l2.4-0.3l1.1-0.5l1.5,1.3l3.7-0.2l1-1.5l-2.9-1.8l-1.9-3.7l-2.1-3.6 l-5.8,2.9L448,625.6z M468.2,634.5l1.3-1.9l4.7,1l0.6-0.5l6.1,0.6l-0.3,1.3l-2.6,1.5l-4.4-0.3L468.2,634.5z M473.5,639.7l1.9,3.9 l3.1-1.1l0.3-1.6l-1.6-2.1l-3.7-0.3V639.7z M480.5,638.5l2.3-2.9l4.7,2.4l4.4,1.1l4.4,2.7v1.9l-3.6,1.8l-4.8,1l-2.4-1.5 L480.5,638.5z M497.1,654.1l1.6-1.3l3.4,1.6l7.6,3.6l3.4,2.1l1.6,2.4l1.9,4.4l4,2.6l-0.3,1.3l-3.9,3.2l-4.2,1.5l-1.5-0.6l-3.1,1.8 l-2.4,3.2l-2.3,2.9l-1.8-0.2l-3.6-2.6l-0.3-4.5l0.6-2.4l-1.6-5.7l-2.1-1.8l-0.2-2.6l2.3-1l2.1-3.1l0.5-1l-1.6-1.8L497.1,654.1z" />
<path id="OK" data-info="<div>State: Oklahoma</div><div>Capital: Oklahoma City</div>" fill="#D3D3D3" d="M549.3,422.6l-10.7-0.5l-6.4-0.5l0.3,0.2l-0.7,10.4l22,1.4l32.1,1.3l-2.3,24.4l-0.5,17.8l0.2,1.6 l4.3,3.7l2.1,1.1l0.7-0.2l0.7-2.1l1.4,1.8h2.1v-1.4l2.7,1.4l-0.5,3.9l4.1,0.2l2.5,1.1l4.1,0.7l2.5,1.8l2.3-2.1l3.4,0.7l2.5,3.4h0.9 v2.3l2.3,0.7l2.3-2.3l1.8,0.7h2.5l0.9,2.5l4.8,1.8l1.4-0.7l1.8-4.1h1.1l1.1,2.1l4.1,0.7l3.7,1.4l3,0.9l1.8-0.9l0.7-2.5h4.3l2.1,0.9 l2.7-2.1h1.1l0.7,1.6h4.1l1.6-2.1l1.8,0.5l2.1,2.5l3.2,1.8l3.2,0.9l1.9,1.1l-0.4-37.2l-1.4-11l-0.2-8.9l-1.4-6.5l-0.8-7.2l-0.1-3.8 l-12.1,0.3l-46.4-0.5l-45-2.1L549.3,422.6z" />
<path id="KS" data-info="<div>State: Kansas</div><div>Capital: Topeka</div>" fill="#D3D3D3" d="M677.4,425.1l-12.6,0.2l-46.1-0.5l-44.6-2.1l-24.6-1.3l4.1-64.7l21.8,0.8l40.5,1.4l44.1,0.5h5.1 l3.2,3.2l2.8,0.2l0.9,1.1v2l-1.8,1.6l-0.5,2.6l2.2,3.6l2.5,3.1l2.5,2l1.1,11.2L677.4,425.1z" />
<path id="LA" data-info="<div>State: Louisiana</div><div>Capital: Baton Rouge</div>" fill="#D3D3D3" d="M776.2,573l-1-2.6l-1.1-3.1l-3.3-3.5l0.9-6.8l-0.1-1.1l-1.3,0.3l-8.2,0.9l-25,0.5l-0.7-2.4l0.9-8.5 l3.3-5.9l5-8.7l-0.6-2.4l1.3-0.7l0.5-2l-2.3-2.1l-0.1-1.9l-1.8-4.3l-0.5-5.9l-9.7,0.1l-19.2,0.9l-22.2,0l0,9.6l0.7,9.4l0.7,3.9 l2.5,4.1l0.9,5l4.3,5.5l0.2,3.2l0.7,0.7l-0.7,8.5l-3,5l1.6,2.1l-0.7,2.5l-0.7,7.3l-1.4,3.2l0.1,3.6l4.7-1.5l8.1-0.3l10.3,3.6 l6.5,1.1l3.7-1.5l3.2,1.1l3.2,1l0.8-2.1l-3.2-1.1l-2.6,0.5l-2.7-1.6c0,0,0.2-1.3,0.8-1.5c0.6-0.2,3.1-1,3.1-1l1.8,1.5l1.8-1 l3.2,0.6l1.5,2.4l0.3,2.3l4.5,0.3l1.8,1.8l-0.8,1.6l-1.3,0.8l1.6,1.6l8.4,3.6l3.6-1.3l1-2.4l2.6-0.6l1.8-1.5l1.3,1l0.8,2.9 l-2.3,0.8l0.6,0.6l3.4-1.3l2.3-3.4l0.8-0.5l-2.1-0.3l0.8-1.6l-0.2-1.5l2.1-0.5l1.1-1.3l0.6,0.8c0,0-0.2,3.1,0.6,3.1 c0.8,0,4.2,0.6,4.2,0.6l4,1.9l1,1.5h2.9l1.1,1l2.3-3.1v-1.5h-1.3l-3.4-2.7l-5.8-0.8l-3.2-2.3l1.1-2.7l2.3,0.3l0.2-0.6l-1.8-1v-0.5 h3.2l1.8-3.1l-1.3-1.9l-0.3-2.7l-1.5,0.2l-1.9,2.1l-0.6,2.6l-3.1-0.6l-1-1.8l1.8-1.9l2-1.8L776.2,573z" />
<path id="VA" data-info="<div>State: Virginia</div><div>Capital: Richmond</div>" fill="#D3D3D3" d="M1002.9,369.2l-0.1-1.9l6.5-2.5l-0.8,3.2l-2.9,3.8l-0.4,4.6l0.5,3.4l-1.8,5l-2.2,1.9l-1.5-4.6 l0.4-5.4l1.6-4.2L1002.9,369.2z M1005.2,397.5L947,410.1l-37.4,5.3l-6.7-0.4l-2.6,1.9l-7.3,0.2l-8.4,1l-8.9,1l8.5-4.9l0-2.1 l1.5-2.1l10.6-11.5l3.9,4.5l3.8,1l2.5-1.1l2.2-1.3l2.5,1.3l3.9-1.4l1.9-4.6l2.6,0.5l2.9-2.1l1.8,0.5l2.8-3.7l0.3-2.1l-1-1.3l1-1.9 l5.3-12.3l0.6-5.7l1.2-0.5l2.2,2.4l3.9-0.3l1.9-7.6l2.8-0.6l1-2.7l2.6-2.3l1.3-2.3l1.5-3.4l0.1-5.1l9.8,3.8 c0.7,0.3,0.7-4.8,0.7-4.8l4.1,1.4l-0.5,2.6l8.2,2.9l1.3,1.8l-0.9,3.7l-1.3,1.3l-0.5,1.7l0.5,2.4l2,1.3l3.9,1.4l2.9,1l4.9,0.9 l2.2,2.1l3.2,0.4l0.9,1.2l-0.4,4.7l1.4,1.1l-0.5,1.9l1.2,0.8l-0.2,1.4l-2.7-0.1l0.1,1.6l2.3,1.5l0.1,1.4l1.8,1.8l0.5,2.5l-2.6,1.4 l1.6,1.5l5.8-1.7L1005.2,397.5z" />
<g id="DC">
<path id="path58" fill="#D3D3D3" d="M975.8,353.8l-1.1-1.6l-1-0.8l1.1-1.6l2.2,1.5L975.8,353.8z" />
<circle id="circle60" data-info="<div>Washington DC</div>" fill="#D3D3D3" stroke="#FFFFFF" stroke- cx="975.3" cy="351.8" r="5" />
</g>
</g>
<path id="path67" fill="none" stroke="#A9A9A9" stroke- d="M385,593v55l36,45 M174,525h144l67,68h86l53,54v46" />
</svg>
</div>
</v-card>
</template>
<script>
Vue.component('geomap-assignments',
template: '#geomap-assignments',
methods:
activateCaption: function (event)
// `event` is the native DOM event
if (event)
const left = this.offsetTop
const top = this.offsetTop
alert("LEFT" + left + "RIGHT" + top);
,
data()
return
documents: [
]
)
</script>
<style scoped>
.card-title-docs
margin: 20px 20px;
.card-header
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
color: #515151;
.card-sub-header
font-size: .8rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: .7px;
color: #7f818d;
.map-container
position:relative;
width: 100%;
height: 100%;
#us-map
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
path:hover, circle:hover
stroke: #002868 !important;
stroke-width: 2px;
stroke-linejoin: round;
fill: #002868 !important;
cursor: pointer;
#path67
fill: none !important;
stroke: #A9A9A9 !important;
cursor: default;
#info-box
display: none;
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
background-color: #ffffff;
border: 2px solid #BF0A30;
border-radius: 5px;
padding: 5px;
font-family: arial;
</style>
'''
【问题讨论】:
CSS 悬停只能影响悬停的元素,或者它之后的元素。这意味着自己、孩子、后来的兄弟姐妹和后来兄弟姐妹的孩子。在您的组件中,#info-box
位于您的 svg
之前,因此 CSS 悬停选择器无法更改其属性。要拥有纯 CSS 解决方案,您需要将 #info-box
放在您的 svg
中,这可能不是您想要的。但是,Vue 解决方案可以正常工作。
@Trevin Avery 是的,更多的挖掘让我意识到纯 css 解决方案可能不实用。我要更新我的问题。在 vueJS 方法中使用纯 JavaScript 可以吗?
那种。你应该避免使用document.getElementById()
之类的东西,因为你的组件可能有多个实例,或者其他组件可能有冲突的 ID。你应该使用$refs
,如果你需要使用vanilla javascript,只需使用$el
(例如this.$refs.infoBox.$el
)从组件中获取元素。添加事件监听器就好了。确保将它们添加到 mounted()
并在 beforeDestroy()
或 destroyed()
中删除它们。
@Trevin Avery 我已经调整了我的代码以改为使用悬停,因为看起来 VueJS mousemove 与仅执行单击事件有点不一致。我已经更新了我上面的问题。我需要获取路径的顶部和左侧位置以显示我的信息框。我尝试了 this.offsetTop 和 this.offsetLeft ,它返回未定义的值。这是因为它是路径元素吗?
我不确定为什么偏移不起作用。但是getBoundingClientRect()
确实有效。您可以在路径上执行此操作以获取视口中路径的左上角。然后,由于您的#info-box
在.map-container
内,您需要调整该容器的位置,或者将#info-box
更改为固定位置。要调整位置,只需在.map-container
或#us-map
上使用getBoundingClientRect()
函数,然后减去顶部和左侧。
【参考方案1】:
在问题的cmets中找到了解决方案。
总之,问题在于理解如何定位#info-box
元素。使用getBoundingClientRect()
函数,我们可以获得任何元素相对于整个文档的位置。要获得点击路径元素的位置,只需从路径的顶部和左侧减去#us-map
的顶部和左侧。这将给出路径左上角相对于包含元素的位置。然后我们可以使用它来定位#info-box
。
【讨论】:
以上是关于纯 Javascript 或 VueJS 事件的 Mousemove 和 Hover Jquery 效果的主要内容,如果未能解决你的问题,请参考以下文章
Vuejs v-for 根据某些条件添加标签属性或事件监听器