class Spoom::Coverage::D3::Timeline
@abstract
def area(y:, color: "#ccc", curve: "curveCatmullRom.alpha(1)")
def area(y:, color: "#ccc", curve: "curveCatmullRom.alpha(1)") <<~HTML svg_#{id}.append("path") .datum(data_#{id}.filter((d) => #{y})) .attr("class", "area") .attr("d", d3.area() .defined((d) => #{y}) .x((d) => xScale_#{id}(parseDate(d.timestamp))) .y0(yScale_#{id}(0)) .y1((d) => yScale_#{id}(#{y})) .curve(d3.#{curve})) .attr("fill", "#{color}") HTML end
def header_script
def header_script <<~JS var parseVersion = function(version) { if (!version) { return null; } return parseFloat(version.replaceAll("0.", "")); } function tooltipTimeline(d, kind) { moveTooltip(d) .html("commit <b>" + d.data.commit + "</b><br>" + d3.timeFormat("%y/%m/%d")(parseDate(d.data.timestamp)) + "<br><br>" + "<b>typed: " + d.key + "</b><br><br>" + "<b>" + (d.data.values[d.key] ? d.data.values[d.key] : 0) + "</b> " + kind +"<br>" + "<b>" + toPercent(d.data.values[d.key] ? d.data.values[d.key] : 0, d.data.total) + "%") } JS end
def header_style
def header_style <<~CSS .domain { stroke: transparent; } .grid line { stroke: #ccc; } .axis text { font: 12px Arial, sans-serif; fill: #333; text-anchor: right; pointer-events: none; } .area { fill-opacity: 0.5; } .line { stroke-width: 2; fill: transparent; } .dot { r: 2; fill: #888; } .inverted .grid line { stroke: #777; } .inverted .area { fill-opacity: 0.9; } .inverted .axis text { fill: #fff; } .inverted .axis line { stroke: #fff; } .inverted .dot { fill: #fff; } CSS end
def initialize(id, data, keys)
def initialize(id, data, keys) super(id, data) @keys = keys end
def line(y:, color: "#ccc", curve: "curveCatmullRom.alpha(1)")
def line(y:, color: "#ccc", curve: "curveCatmullRom.alpha(1)") <<~HTML svg_#{id}.append("path") .datum(data_#{id}.filter((d) => #{y})) .attr("class", "line") .attr("d", d3.line() .x((d) => xScale_#{id}(parseDate(d.timestamp))) .y((d) => yScale_#{id}(#{y})) .curve(d3.#{curve})) .attr("stroke", "#{color}") HTML end
def plot; end
- Abstract: -
def plot; end
def points(y:)
def points(y:) <<~HTML svg_#{id}.selectAll("circle") .data(data_#{id}) .enter() .append("circle") .attr("class", "dot") .attr("cx", (d) => xScale_#{id}(parseDate(d.timestamp))) .attr("cy", (d, i) => yScale_#{id}(#{y})) .on("mouseover", (d) => tooltip.style("opacity", 1)) .on("mousemove", tooltip_#{id}) .on("mouseleave", (d) => tooltip.style("opacity", 0)); HTML end
def script
@override
def script <<~HTML #{tooltip} var data_#{id} = #{@data.to_json}; function draw_#{id}() { var width_#{id} = document.getElementById("#{id}").clientWidth; var height_#{id} = 200; d3.select("##{id}").selectAll("*").remove() var svg_#{id} = d3.select("##{id}") .attr("width", width_#{id}) .attr("height", height_#{id}) #{plot} } draw_#{id}(); window.addEventListener("resize", draw_#{id}); HTML end
def x_scale
def x_scale <<~HTML var xScale_#{id} = d3.scaleTime() .range([0, width_#{id}]) .domain(d3.extent(data_#{id}, (d) => parseDate(d.timestamp))); svg_#{id}.append("g") .attr("class", "grid") .attr("transform", "translate(0," + height_#{id} + ")") .call(d3.axisBottom(xScale_#{id}) .tickFormat("") .tickSize(-height_#{id})) HTML end
def x_ticks
def x_ticks <<~HTML svg_#{id}.append("g") .attr("class", "axis x") .attr("transform", "translate(0," + height_#{id} + ")") .call(d3.axisBottom(xScale_#{id}) .tickFormat(d3.timeFormat("%y/%m/%d")) .tickPadding(-15) .tickSize(-3)); HTML end
def y_scale(min:, max:, ticks:)
def y_scale(min:, max:, ticks:) <<~HTML var yScale_#{id} = d3.scaleLinear() .range([height_#{id}, 0]) .domain([#{min}, #{max}]); svg_#{id}.append("g") .attr("class", "grid") .call(d3.axisLeft(yScale_#{id}) .#{ticks} .tickFormat("") .tickSize(-width_#{id})) HTML end
def y_ticks(ticks:, format:, padding:)
def y_ticks(ticks:, format:, padding:) <<~HTML svg_#{id}.append("g") .attr("class", "axis y") .call(d3.axisLeft(yScale_#{id}) .#{ticks} .tickSize(-3) .tickFormat((d) => #{format}) .tickPadding(-#{padding})) HTML end