【发布时间】:2014-05-21 02:52:11
【问题描述】:
我在两个 svg 元素上应用了 mouseover/mouseout 事件。目标是将mouseover 上的掩码半径增加到由变量(maxMaskRadius)指定的大小,并将mouseout 上的decrease 增加到初始状态(initialMaskRadius)。
我只使用一个元素就可以完美地工作。但是当我有两个元素并从一个元素悬停到另一个元素时,前一个元素的动画会立即中止。但我想让它动画回到它的初始状态。不幸的是,使用我当前的代码是不可能的。
关于如何正确执行此操作的任何建议?
CSS:
.dday.highlight .overlay {
fill: rgba(247,99,62,0.8);
}
.dday.normal {
width: 288px;
height: 288px;
}
HTML:
<svg class="dday highlight normal" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-image="car.jpg">
<image height="196" width="250" />
<a class="overlay" xlink:href="/svg/index.html" target="_top">
<rect x="0" y="0" width="288" height="288" style="mask: url(#mask1)" onmouseover="initAnimation(evt)" onmouseout="initAnimation(evt)" />
</a>
<mask id="mask1">
<rect x="0" y="0" width="288" height="288" fill="#fff" />
<circle cx="125" cy="125" r="25" />
</mask>
</svg>
<svg class="dday highlight normal" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-image="nokia.jpg">
<image height="196" width="250" />
<a class="overlay" xlink:href="/svg/index.html" target="_top">
<rect x="0" y="0" width="288" height="288" style="mask: url(#mask2)" onmouseover="initAnimation(evt)" onmouseout="initAnimation(evt)" />
</a>
<mask id="mask2">
<rect x="0" y="0" width="288" height="288" fill="#fff" />
<circle cx="125" cy="125" r="25" />
</mask>
</svg>
JS:
var maxImageWidth = 250,
maxImageHeight = 196,
ease = 50,
speed = 12,
maxMaskRadius = 100,
svg = null,
svgWidth = null,
svgHeight = null,
mask = null,
maskRadius = null,
initialMaskRadius = null,
imageObj = [],
imageSrcs = [],
imageWidth = null,
imageHeight = null,
mouseEvent = null;
init();
function init(el, index) {
$('.dday').each(function(index){
defineCurrentElement(this, index);
positionMask();
});
}
function defineCurrentElement(el, index) {
// Redefine the current Element
svg = $(el).closest('.dday'),
svgWidth = svg.width(),
svgHeight = svg.height(),
mask = svg.find('circle')[0];
// On page load there is a index provided to load the images for each element
if(typeof index !== 'undefined'){
loadImage(index);
}
}
function loadImage(index) {
// Load images and scale them to fit the predefined area
imageSrcs[index] = svg.data('image');
imageObj[index] = new Image(),
imageObj[index].image = $('image')[index];
imageObj[index].onload = function(){
scale_width = maxImageWidth / this.width;
scale_height = maxImageHeight / this.height;
scale = Math.min(scale_width, scale_height);
imageWidth = this.width * scale;
imageHeight = this.height * scale;
var xCoordinate = (svgWidth - imageWidth) / 2,
yCoordinate = (svgHeight - imageHeight) / 2;
this.image.setAttributeNS('http://www.w3.org/1999/xlink','href', imageSrcs[index]);
this.image.setAttributeNS(null,'width', imageWidth);
this.image.setAttributeNS(null,'height', imageHeight);
this.image.setAttributeNS(null,'x', xCoordinate);
this.image.setAttributeNS(null,'y', yCoordinate);
};
imageObj[index].src = imageSrcs[index];
}
function initAnimation(ev) {
// Triggered on mouseover/-out
// Change current element and init animation
defineCurrentElement(ev.target);
mouseEvent = ev.type;
requestAnimationFrame(animate);
}
function animate() {
if(mouseEvent == 'mouseover') {
// Increase mask radius on mouseover and repeat until target state is reached
maskRadius += Math.round(Math.max(((maxMaskRadius-maskRadius)/ease) * speed, 0.5));
if(maskRadius >= maxMaskRadius) {
// Target radius has been reached
maskRadius = maxMaskRadius;
} else {
// Target radius hasn't been reached yet -> repeat animation
mask.setAttributeNS(null,'r', maskRadius);
requestAnimationFrame(animate);
}
} else {
// Decrease mask radius on mouseover and repeat until initial state is reached
maskRadius -= Math.max(((maskRadius-initialMaskRadius)/ease) * speed, 0.5);
if(maskRadius <= initialMaskRadius) {
// Target radius has been reached
maskRadius = initialMaskRadius;
} else {
// Target radius hasn't been reached yet -> repeat animation
mask.setAttributeNS(null,'r', maskRadius);
requestAnimationFrame(animate);
}
}
}
function positionMask() {
// Center mask inside element
maskRadius = initialMaskRadius = parseInt(mask.getAttributeNS(null, 'r'), 10);
var maskWidth = maskRadius * 2,
xCoordinate = (svgWidth - maskWidth) / 2 + maskRadius,
yCoordinate = (svgHeight - maskWidth) / 2 + maskRadius;
mask.setAttributeNS(null,'cx', xCoordinate);
mask.setAttributeNS(null,'cy', yCoordinate);
}
【问题讨论】:
-
无法打开 DEMO :(
-
@VivekParekh 您使用哪种浏览器?我觉得jsfiddle支持IE9+,希望大家不要使用以下任何版本!
-
我使用 chrome。控制台显示错误。页面一直在加载。
-
@VivekParekh 我已经用相关代码更新了我的问题..
-
你的代码很糟糕。但我正在尝试重构您的代码以使用任意数量的
标签: javascript jquery svg hover mouseover