Javascript 如何使SVG元素鼠标事件通过另一个元素弹出?
我有一个D3折线图,我把一个矩形放在图表后面。这个矩形有一个鼠标事件附加到它,但问题是我的图表也有另一个矩形覆盖在图表的“上面”,图表也有附加到它的事件 如何使下矩形鼠标事件在覆盖在顶部的高矩形上方冒泡?非常感谢 我在这里创作了一把小提琴: 这是我的密码。查看“这是我需要鼠标盖冒泡的地方”评论,看看我想冒泡的元素Javascript 如何使SVG元素鼠标事件通过另一个元素弹出?,javascript,svg,d3.js,Javascript,Svg,D3.js,我有一个D3折线图,我把一个矩形放在图表后面。这个矩形有一个鼠标事件附加到它,但问题是我的图表也有另一个矩形覆盖在图表的“上面”,图表也有附加到它的事件 如何使下矩形鼠标事件在覆盖在顶部的高矩形上方冒泡?非常感谢 我在这里创作了一把小提琴: 这是我的密码。查看“这是我需要鼠标盖冒泡的地方”评论,看看我想冒泡的元素 var data = [ {"date":"1-May-13","close":58.13}, {"date":"30-Apr-13","close":53.98}, {
var data = [
{"date":"1-May-13","close":58.13},
{"date":"30-Apr-13","close":53.98},
{"date":"27-Apr-13","close":67.00},
{"date":"26-Apr-13","close":89.70},
{"date":"25-Apr-13","close":99.00},
{"date":"24-Apr-13","close":130.28},
{"date":"23-Apr-13","close":166.70},
{"date":"20-Apr-13","close":234.98},
{"date":"19-Apr-13","close":345.44},
{"date":"18-Apr-13","close":443.34},
];
var margin = {top: 20, right: 50, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse,
bisectDate = d3.bisector(function(d) { return d.date; }).left,
formatValue = d3.format(",.2f"),
formatCurrency = function(d) { return "$" + formatValue(d); };
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
data.sort(function(a, b) {
return a.date - b.date;
});
x.domain([data[0].date, data[data.length - 1].date]);
y.domain(d3.extent(data, function(d) { return d.close; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price ($)");
<!-- This is where I need the mouseover to bubble up -->
var left = x(new Date("Apr 23 2013"));
var right = x(new Date("Apr 26 2013"));
var wid = right - left;
svg.append("rect")
.attr("id", "range")
.attr("class", "range")
.attr("x", left)
.attr("width", wid)
.attr("height", height)
.on("mouseover", function () {
alert("I can see you!");
})
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
var focus = svg.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("circle")
.attr("r", 4.5);
focus.append("text")
.attr("x", 9)
.attr("dy", ".35em");
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")");
focus.select("text").text(formatCurrency(d.close));
}
});
var数据=[
{“日期”:“2013年5月1日”,“结束”:58.13},
{“日期”:“2013年4月30日”,“截止日期”:53.98},
{“日期”:“2013年4月27日”,“截止日期”:67.00},
{“日期”:“2013年4月26日”,“截止日期”:89.70},
{“日期”:“2013年4月25日”,“截止日期”:99.00},
{“日期”:“2013年4月24日”,“截止日期”:130.28},
{“日期”:“2013年4月23日”,“截止日期”:166.70},
{“日期”:“2013年4月20日”,“截止日期”:234.98},
{“日期”:“2013年4月19日”,“结束”:345.44},
{“日期”:“2013年4月18日”,“截止日期”:443.34},
];
var margin={顶部:20,右侧:50,底部:30,左侧:50},
宽度=960-margin.left-margin.right,
高度=500-margin.top-margin.bottom;
var parseDate=d3.time.format(“%d-%b-%y”).parse,
平分日期=d3.平分线(函数(d){return d.date;})。左,
formatValue=d3.format(“,.2f”),
formatCurrency=函数(d){return“$”+formatValue(d);};
var x=d3.time.scale()
.范围([0,宽度]);
变量y=d3.scale.linear()
.范围([高度,0]);
var xAxis=d3.svg.axis()
.比例(x)
.东方(“底部”);
var yAxis=d3.svg.axis()
.比例(y)
.东方(“左”);
var line=d3.svg.line()
.x(函数(d){返回x(d.date);})
.y(函数(d){返回y(d.close);});
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
data.forEach(函数(d){
d、 日期=解析日期(d.date);
d、 close=+d.close;
数据排序(函数(a,b){
返回a.日期-b.日期;
});
x、 域([data[0].date,data[data.length-1].date]);
y、 域(d3.extent(数据,函数(d){返回d.close;}));
svg.append(“g”)
.attr(“类”、“x轴”)
.attr(“变换”、“平移(0)”、“高度+”)
.呼叫(xAxis);
svg.append(“g”)
.attr(“类”、“y轴”)
.呼叫(yAxis)
.append(“文本”)
.attr(“变换”、“旋转(-90)”)
.attr(“y”,6)
.attr(“dy”,“.71em”)
.style(“文本锚定”、“结束”)
.text(“价格($)”);
左var=x(新日期(“2013年4月23日”);
var right=x(新日期(“2013年4月26日”);
var wid=右-左;
svg.append(“rect”)
.attr(“id”、“范围”)
.attr(“类别”、“范围”)
.attr(“x”,左)
.attr(“宽度”,宽度)
.attr(“高度”,高度)
.on(“鼠标悬停”,函数(){
警惕(“我能看见你!”);
})
追加(“路径”)
.基准(数据)
.attr(“类”、“行”)
.attr(“d”,行);
var focus=svg.append(“g”)
.attr(“类”、“焦点”)
.样式(“显示”、“无”);
焦点。附加(“圆”)
.attr(“r”,4.5);
focus.append(“文本”)
.attr(“x”,9)
.attr(“dy”,“.35em”);
svg.append(“rect”)
.attr(“类”、“覆盖”)
.attr(“宽度”,宽度)
.attr(“高度”,高度)
.on(“mouseover”,function(){focus.style(“display”,null);})
.on(“mouseout”,function(){focus.style(“display”,“none”);})
.on(“mousemove”,mousemove);
函数mousemove(){
var x0=x.invert(d3.mouse(this)[0]),
i=平分日期(数据,x0,1),
d0=数据[i-1],
d1=数据[i],
d=x0-d0.date>d1.date-x0?d1:d0;
attr(“transform”、“translate”(+x(d.date)+)、“+y(d.close)+”);
焦点。选择(“文本”)。文本(格式货币(d.close));
}
});
要快速修复此问题,您可以将范围移动到覆盖上方,并从该范围手动调用覆盖事件处理程序
冒泡是在dom级别进行的,因为没有办法让一个rect成为另一个rect的子rect,所以冒泡不会为您解决这个问题。将元素组合在一起并在组中放置一个检查事件目标的处理程序将阻止您两次注册事件处理程序,但会遇到相同的基本问题:当元素重叠时,在源顺序中最后声明的元素将获得事件。您也可以使用以下样式“隐藏”鼠标事件的某些svg元素。在我的例子中,我想通过的是
mouseover
事件:
pointer-events: none;
以上所有答案都是正确的,但我想再举一个例子:
let log = console.log
let data = []
let pointStart = document.querySelector("svg").createSVGPoint()
let pointStop = document.querySelector("svg").createSVGPoint()
let divLog = d3.select("#log")
var svg = d3.select("svg")
var linearfn = d3.line()
.x(d => d.x)
.y(d => d.y)
.curve(d3.curveLinear)
function logTagName(eventName, tagName) {
divLog.html(divLog.html() + eventName + " : " + tagName + "<br/>")
}
svg.on("click", function() {
log("tagName: ", event.target.tagName)
logTagName("svg click", event.target.tagName)
pointStart.x = event.x - 8
pointStart.y = event.y - 8
data.push({
x: pointStart.x,
y: pointStart.y
})
svg.selectAll("path") // SVG içinde tanımlı path elemanlarını bul
.data([1]).enter() // 1 elemanlı dizinin eleman sayısı kadarı için enter()
.append('path') // dizi elemanı kadar path oluştur
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 8)
.attr("d", linearfn(data))
.on("click", function() {
log("tagName: ", event.target.tagName)
logTagName("path click", event.target.tagName)
/* click event will start from path and pass to the svg element */
// event.stopPropagation(); // letting pass event bubbling
})
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d => d.x + .5)
.attr("cy", d => d.y + .5)
.attr("r", 20)
.attr("stroke-width", 3)
.attr("stroke", "red")
.attr("cursor", "move")
.style("fill", "transparent")
.attr("pointer-events", "all") // when clicked in/outside of circle, it'll handle events
.on("mouseover", function() {
log("over oldu")
d3.select(this).style("stroke", "blue");
})
.on("mouseout", function() {
log("out oldu")
d3.select(this).style("stroke", "red");
})
.on("click", function() {
event.stopPropagation(); // not letting pass event bubbling
event.preventDefault();
log("click oldu")
d3.select(this).style("stroke", "black");
})
})
.on("mousemove", function() {
// fare hareketinde de çizdireceğiz ama x,y noktasını
// tıklanıncaya kadar diziye eklemeyeceğiz
pointStop.x = event.x - 8
pointStop.y = event.y - 8
svg.select("path")
.attr("d", linearfn(data.concat({
x: pointStop.x,
y: pointStop.y
})))
})
let log=console.log
让数据=[]
让pointStart=document.querySelector(“svg”).createSVGPoint()
让pointStop=document.querySelector(“svg”).createSVGPoint()
让divLog=d3。选择(“#log”)
var svg=d3.选择(“svg”)
变量linearfn=d3.line()
.x(d=>d.x)
.y(d=>d.y)
.曲线(d3.曲线线)
函数logTagName(事件名,标记名){
html(divLog.html()+eventName+“:“+tagName+”
)
}
打开(“单击”,函数(){
日志(“标记名:”,事件.target.tagName)
logTagName(“svg单击”,event.target.tagName)
pointStart.x=event.x-8
pointStart.y=event.y-8
数据推送({
x:pointStart.x,
y:pointStart.y
})
svg.selectAll(“path”)//svg içinde tanımlıpath elemanlarınıbul
.data([1]).enter()//1 elemanlıdizinin eleman sayısıkadarıiçin enter()
.append('path')//dizi elemanıkadar path oluştur
.attr(“填充”、“无”)
.attr(“笔划”、“黑色”)
.attr(“笔划宽度”,8)
.attr(“d”,linearfn(数据))
.on(“单击”,函数(){
日志(“标记名:”,事件.target.tagName)
logTagName(“路径单击”,事件.target.tagName)
/*单击事件将从路径开始并传递到svg元素*/
//event.sto
let log = console.log
let data = []
let pointStart = document.querySelector("svg").createSVGPoint()
let pointStop = document.querySelector("svg").createSVGPoint()
let divLog = d3.select("#log")
var svg = d3.select("svg")
var linearfn = d3.line()
.x(d => d.x)
.y(d => d.y)
.curve(d3.curveLinear)
function logTagName(eventName, tagName) {
divLog.html(divLog.html() + eventName + " : " + tagName + "<br/>")
}
svg.on("click", function() {
log("tagName: ", event.target.tagName)
logTagName("svg click", event.target.tagName)
pointStart.x = event.x - 8
pointStart.y = event.y - 8
data.push({
x: pointStart.x,
y: pointStart.y
})
svg.selectAll("path") // SVG içinde tanımlı path elemanlarını bul
.data([1]).enter() // 1 elemanlı dizinin eleman sayısı kadarı için enter()
.append('path') // dizi elemanı kadar path oluştur
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 8)
.attr("d", linearfn(data))
.on("click", function() {
log("tagName: ", event.target.tagName)
logTagName("path click", event.target.tagName)
/* click event will start from path and pass to the svg element */
// event.stopPropagation(); // letting pass event bubbling
})
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d => d.x + .5)
.attr("cy", d => d.y + .5)
.attr("r", 20)
.attr("stroke-width", 3)
.attr("stroke", "red")
.attr("cursor", "move")
.style("fill", "transparent")
.attr("pointer-events", "all") // when clicked in/outside of circle, it'll handle events
.on("mouseover", function() {
log("over oldu")
d3.select(this).style("stroke", "blue");
})
.on("mouseout", function() {
log("out oldu")
d3.select(this).style("stroke", "red");
})
.on("click", function() {
event.stopPropagation(); // not letting pass event bubbling
event.preventDefault();
log("click oldu")
d3.select(this).style("stroke", "black");
})
})
.on("mousemove", function() {
// fare hareketinde de çizdireceğiz ama x,y noktasını
// tıklanıncaya kadar diziye eklemeyeceğiz
pointStop.x = event.x - 8
pointStop.y = event.y - 8
svg.select("path")
.attr("d", linearfn(data.concat({
x: pointStop.x,
y: pointStop.y
})))
})