D3.js 雙按滑鼠二下加入標註文字到圖形裡
由於要修改為另一版本的新程式碼,因此紀錄舊程式碼如下:
function FocusTrendChartMeasureExistData(data, maxSize, minSize) {
d3.selectAll(".linechartMeasure g").remove();
var linechart = d3.select(".linechartMeasure"),
margin = { top: 20, right: 165, bottom: 30, left: 80 },
width = parseInt(d3.select(".chart_in").style("width")) - margin.left - margin.right - 50,
height3 = 200 - margin.top - margin.bottom,
radius = 6;
g = linechart.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var svg = d3.select(".linechartMeasure")
.attr("width", width + margin.left + margin.right)
.attr("height", height3 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var parseTime = d3.timeParse("%Y%m%d %H:%M");
var xScale = d3.scaleTime().range([0, width]),
yScale = d3.scaleLinear().range([height3, 0]);
// set the colour scale
var color = d3.scaleOrdinal(d3.schemeCategory10);
var lineGenerator = d3.line()
.curve(d3.curveCardinal);
var line = lineGenerator
.x(function (d) {
return xScale(d.date);
})
.y(function (d) {
return yScale(d.Size);
});
var jsonArray = [];
var jsObject = $.parseJSON(data.replace(/\"/g, '"'));
$.each(jsObject, function (index, obj) {
jsonArray.push(obj);
});
var equipmentData = jsonArray.map(function (main) {
return {
id: main.EquipmentName,
values: main.detailResults.map(function (detail) {
return {
date: parseTime(detail.ProcessTime),
Size: detail.Size
}
}),
EDCItemName: main.EDCItemName
};
});
var labelName = jsonArray.map(function (main) {
return {
EDCItemName: main.EDCItemName
};
});
//填充日期陣列
var dataNest = d3.nest()
.key(function (dn) {
return dn.EquipmentName;
}).entries(jsonArray);
var dataArray = [];
dataNest.forEach(function (dns, i) {
var id = dns.key;
var value = dns.values[0];
value.detailResults.forEach(function (detail, j) {
dataArray.push(parseTime(detail.ProcessTime));
})
});
//將日期陣列放入尺度範圍
xScale.domain(d3.extent(dataArray, function (d) {
return d;
}));
yScale.domain([
d3.min(equipmentData, function (c) {
if (minSize != null && !isNaN(minSize)) {
return minSize;
}
else {
return d3.min(c.values, function (d) {
return d.Size;
});
}
}),
d3.max(equipmentData, function (c) {
if (maxSize != null && !isNaN(maxSize)) {
return maxSize;
}
else {
return d3.max(c.values, function (d) {
return d.Size;
});
}
})
]);
color.domain(equipmentData.map(function (c) {
return c.id;
}));
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height3 + ")")
.call(d3.axisBottom(xScale));
var edcItemName = "";
if (labelName != null && labelName.length > 0) {
//括號內應是檢查製程
var checkOperationName = '@Model.ShowSearchItemToolBar.CheckOperation';
edcItemName = labelName[0].EDCItemName + "(" + checkOperationName + ")";
}
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(yScale))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -46)
.attr("dy", "0.71em")
.attr("fill", "#000")
.attr("font-size", 12)
.text(edcItemName);
var trend =
g.selectAll(".trend")
.data(equipmentData)
.enter().append("g")
.attr("class", "trend");
trend.append("path")
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", "1.5px")
.attr("d", function (dns) {
return line(dns.values);
})
.style("stroke", function (dns) {
return color(dns.id);
});
equipmentData.forEach(function (dns, i) {
var details = dns.values;
//增加點上的文字
svg.selectAll(".dottxt" + i)
.data(details)
.enter().append("text")
.attr("class", "dottxt")
.attr("x", function (sub) {
return xScale(sub.date);
})
.attr("y", function (sub) {
return yScale(sub.Size);
})
.style("fill", function () {
return color(dns.id);
})
.text(function (sub) {
return sub.Size;
});
//增加線上的圓點
svg.selectAll("circle" + i)
.data(details)
.enter().append("circle")
.attr("r", 4)
.attr("cx", function (sub) {
return xScale(sub.date);
})
.attr("cy", function (sub) {
return yScale(sub.Size);
})
.style("fill", function () {
return color(dns.id);
})
.append("text")
.attr("class", "dottxt")
.style("fill", "#000");
//色塊圖例
var xNameArea = svg.append("g")
.attr("transform", "translate(0," + i * 20 + ")");
xNameArea.append("rect")
.attr("x", width + 5)
.attr("y", 10)
.attr("width", 19)
.attr("height", 19)
.attr("fill", color(dns.id));
xNameArea.append("text")
.attr("x", width + 25)
.attr("y", 20)
.attr("dy", "0.32em")
.attr("font-size", 11)
.text(dns.id);
});
var dataset = [];
//按下加入標註文字到圖形裡
linechart.on("dblclick", function () {
var coords = d3.mouse(this);
var newData = {
x: Math.round(coords[0]),
y: Math.round(coords[1]),
text: "@Resource.PleaseInputRemarkName"
};
dataset.push(newData);
linechart.append('text')
.attr("id", "remarkText")
.attr("x", newData.x)
.attr("y", newData.y)
.attr('text-anchor', 'middle')
.on("mouseover", function () {
d3.select(this).style("fill", "blue");
})
.text(newData.text)
.on("click", function () {
var p = this.parentNode;
console.log(this, arguments);
var xy = this.getBBox();
var p_xy = p.getBBox();
xy.x -= p_xy.x;
xy.y -= p_xy.y;
var el = d3.select(this);
var p_el = d3.select(p);
var frm = p_el.append("foreignObject");
var inp = frm
.attr("x", xy.x)
.attr("y", xy.y)
.attr("width", 300)
.attr("height", 25)
.append("xhtml:form")
.append("input")
.attr("value", function () {
this.focus();
return newData.text;
})
.attr("style", "width: 294px;")
// make the form go away when you jump out (form looses focus) or hit ENTER:
.on("blur", function () {
console.log("blur", this, arguments);
var txt = inp.node().value;
newData.text = txt;
el.text(function (d) {
return newData.text;
});
// Note to self: frm.remove() will remove the entire <g> group! Remember the D3 selection logic!
p_el.select("foreignObject").remove();
})
.on("keypress", function () {
console.log("keypress", this, arguments);
// IE fix
if (!d3.event)
d3.event = window.event;
var e = d3.event;
if (e.keyCode == 13) {
if (typeof (e.cancelBubble) !== 'undefined') // IE
e.cancelBubble = true;
if (e.stopPropagation)
e.stopPropagation();
e.preventDefault();
var txt = inp.node().value;
newData.text = txt;
el.text(function (d) {
return newData.text;
});
// odd. Should work in Safari, but the debugger crashes on this instead.
// Anyway, it SHOULD be here and it doesn't hurt otherwise.
p_el.select("foreignObject").remove();
}
});
});
});