我正在使用带有缩放功能的D3.js区域图。工具提示功能。我正在长按(触摸或鼠标按下)&在鼠标上工具提示停止。
如果图表未缩放,则工具提示会正确显示,但如果图表缩放,则工具提示未正确更新。
任何帮助将不胜感激。请检查创建的小提琴:
var date_format = d3.time.format("%b'%y"),
commaFormat = d3.format(',');
var margin = {
top: 0,
right: 10,
bottom: 45,
left: 75
};
var stopMove = false,pressTimer, startZoom = true, touchTime = 0, showTooltip = false, ct = 0, savedScale, saveTrans;
var width = 900 - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
var bisectDate = d3.bisector(function (d) {
return new Date(d.date);
}).left,formatDate = d3.time.format("%d-%b");;
var x = d3.time.scale()
.domain([new Date(data[0].date), d3.time.day.offset(new Date(data[data.length - 1].date), 1)])
.range([0, width]);
var y = d3.scale.linear()
.domain(d3.extent(data, function (d) {
return d.balance;
}))
.range([height, 0]);
area = d3.svg.area()
.x(function (d) {
return x(new Date(d.date));
})
.y0(height)
.y1(function (d) {
return y(d.balance);
});
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([1, 10])
.on("zoom", zoomed);
svg = d3.select("body").append("svg")
.append("svg:svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
svg.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(-height)
.tickFormat(date_format);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickSize(-width)
.tickFormat(function (d) {
return d;
});
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", (0 - margin.left))
.attr("x", 0 - ((height) / 2))
.attr("dy", "1em")
.style("display", 'none')
.style("text-anchor", "middle")
.style("font-size", "11px")
.style("font-weight", "bold")
.text("Daily Balance");
svg.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.style("color", "#333")
.attr("dx", "-1.1em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-45)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr("class", "area")
.attr("d", area);
var focus = svg.append("g")
.style("display", "none");
focus.append("line")
.attr("class", "x")
.style("stroke", "darkblue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("y1", 0)
.attr("y2", height);
focus.append("line")
.attr("class", "y")
.style("stroke", "darkblue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("x1", width)
.attr("x2", width);
focus.append("circle")
.attr("class", "y")
.style("fill", "none")
.style("stroke", "darkblue")
.attr("r", 4);
focus.append("text")
.attr("class", "y1")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "-.3em");
focus.append("text")
.attr("class", "y2")
.attr("dx", 8)
.attr("dy", "-.3em");
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.on("mousedown", function () { touchTime = touchTime + 1; console.log("mouseStart touchTime" + touchTime);
if (touchTime == 1) {
ct = 1;
pressTimer = window.setTimeout(function () {
svg.call(zoom)
.on("zoom", null)
.on("mouseout.zoom", null)
.on("mouseover.zoom", null)
.on("mousemove.zoom", null)
.on("touchstart.zoom",
function () {
stopMove = true;
console.log("mouseDtart in zoomdisabled");
})
.on("touchmove.zoom", null)
.on("touchend.zoom", null);
startZoom = false;
console.log("show tooltip"); showTooltip = true; focus.style("display", null);//}
}, 1000)
}
}
)
.on("mouseup", function () { focus.style("display", "none");
touchTime = 0;
if (showTooltip) { startZoom = true; }
showTooltip = false;
console.log("touchend touchTime" + touchTime + " cleartimeout=" + ct);
if (ct == 1) {
window.clearTimeout(pressTimer);
startZoom = true;
ct = 0;
}
})
.on("touchend", function () {
focus.style("display", "none");
touchTime = 0;
if (showTooltip) { startZoom = true; }
showTooltip = false;
console.log("touchend touchTime" + touchTime + " cleartimeout=" + ct);
if (ct == 1) {
window.clearTimeout(pressTimer);
startZoom = true;
ct = 0;
}
})
.on("touchstart", function () {
touchTime = touchTime + 1; console.log("touchstart touchTime" + touchTime);
if (touchTime == 1) {
ct = 1;
pressTimer = window.setTimeout(function () {
svg.call(zoom)
.on("zoom", null)
.on("mouseout.zoom", null)
.on("mouseover.zoom", null)
.on("mousemove.zoom", null)
.on("touchstart.zoom",
function () {
stopMove = true;
console.log("touchstart in zoomdisabled");
})
.on("touchmove.zoom", null)
.on("touchend.zoom", null);
startZoom = false;
console.log("show tooltip"); showTooltip = true; focus.style("display", null);//}
}, 1000)
}
}
)
.on("mousemove", mousemove)
.on("touchmove", mousemove);
function mousemove() {
if (ct == 1) {
console.log("clear timeout");
window.clearTimeout(pressTimer);
ct = 0;
}
if (showTooltip) {
console.log("this1=" + x(d3.mouse(this)[0]));
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1);
console.log("x0=" + x0);
if (i < data.length) {
var d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.select("circle.y")
.attr("transform", "translate(" + x(new Date(d.date)) + "," + y(d.balance) + ")");
focus.select("text.y1")
.attr("transform", "translate(" + x(new Date(d.date)) + "," + y(d.balance) + ")")
.text(commaFormat(d.balance));
focus.select("text.y2")
.attr("transform", "translate(" + x(new Date(d.date)) + "," + y(d.balance) + ")")
.text(commaFormat(d.balance));
focus.select(".x")
.attr("transform", "translate(" + x(new Date(d.date)) + "," + y(d.balance) + ")")
.attr("y2", height - y(d.balance));
focus.select(".y")
.attr("transform", "translate(" + width * -1 + "," + y(d.balance) + ")")
.attr("x2", width + width);
}
}
}
function zoomed() {
var translate = zoom.translate(),
scale = zoom.scale();
console.log("translate="+translate+" scale="+scale);
tx = Math.min(0, Math.max(width * (1 - scale), translate[0]));
ty = Math.min(0, Math.max(height * (1 - scale), translate[1]));
zoom.translate([tx, ty]);
if (startZoom) {
svg.select(".y.axis").call(yAxis);
svg.select(".x.axis").call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.style("color", "#333")
.attr("dx", "-1.1em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-45)");
svg.select(".area")
.attr("class", "area")
.attr("d", area);
}
}