From b8570ae0a7bd187e06e4d04643799a037581b94f Mon Sep 17 00:00:00 2001 From: tacit0428 Date: Wed, 3 Aug 2022 18:14:54 +0800 Subject: [PATCH] establishment --- src/spec/barchart.json | 155 +++++++++++++++++----------- src/vis/actions/addimage.js | 3 +- src/vis/charts/areachart/index.js | 60 ++++++++--- src/vis/charts/barchart/index.js | 60 ++++++++--- src/vis/charts/hbarchart/index.js | 60 ++++++++--- src/vis/charts/linechart/index.js | 66 +++++++++--- src/vis/charts/piechart/index.js | 66 +++++++++--- src/vis/charts/scatterplot/index.js | 62 ++++++++--- src/vis/charts/unitvis/index.js | 66 +++++++++--- 9 files changed, 445 insertions(+), 153 deletions(-) diff --git a/src/spec/barchart.json b/src/spec/barchart.json index 728f13a..f0c7be1 100644 --- a/src/spec/barchart.json +++ b/src/spec/barchart.json @@ -1,45 +1,64 @@ { "data": { - "url": "http://localhost:3000/spreadsheets/sales.csv", + "url": "https://narchart.github.io/editor/spreadsheets/deadstartup.csv", "schema": [ { - "field": "Year", - "type": "temporal" + "field": "industry", + "type": "categorical" }, { - "field": "Brand", + "field": "funded status", "type": "categorical" }, { - "field": "Category", + "field": "cause of failure", "type": "categorical" }, { - "field": "Sales", + "field": "broken year", + "type": "temporal" + }, + { + "field": "survival time", "type": "numerical" + }, + { + "field": "location", + "type": "categorical" } ] }, - "actions": [ { "add": "config", - "mode": "light", - "emotion": "exciting" + "mode": "dark", + "emotion": "disturbing" }, { "select": [ { - "field": "Sales", - "aggregate": "min" + "field": "survival time", + "aggregate": "average" + }, + { + "field": "location" }, { - "field": "Brand" + "field": "funded status" + }, + { + "field": "broken year" + }, + { + "field": "industry" + }, + { + "field": "cause of failure" } ], "groupby": [ { - "field": "Brand" + "field": "funded status" } ], "filter": [] @@ -49,88 +68,108 @@ "mark": { "type": "bar", "style": { - "corner-radius": 8, - "bin-spacing": 0.5, - "stroke": "#FFBE32", - "stroke-width": 3, - "stroke-opacity": 1, - "fill-opacity": 1 + "bin-spacing": 0.3, + "corner-radius": 3, + "stroke-width": 1, + "stroke": "white" + } + }, + "style": { + "background-image": { + "url": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" + }, + "background-color": { + "color": "gray" } } }, + { + "add": "title", + "text": "Dead startups in China", + "style": { + "font-color": "#FE5C34", + "font-size": 37, + "font-family": "Georgia", + "font-style": "italic", + "position": "top-left" + }, + "animation": { + "duration": 1000 + } + }, + { + "add": "caption", + "text": "We collected data from itjuzi.com and analyzed the startups in China died between 2010 and 2019. Companies that go public have the longest mean survival time.", + "style": { + "font-color": "#FE5C34", + "font-size": 15, + "position": "top-left", + "top-padding": 5 + }, + "animation": { + "duration": 1000 + } + }, { "add": "group", "actions": [ { "add": "encoding", "channel": "x", - "field": "Brand" + "field": "funded status" }, { "add": "encoding", "channel": "y", - "field": "Sales" - } - ] - }, - { - "add": "annotation", - "method": "label", - "target": [ - { - "field": "Brand", - "value": "Ford" + "field": "survival time" } ], - "style": { - "font-size": 20, - "font-family": "sans-serif", - "font-color": "red", - "font-weight": 300, - "font-style": "italic" + "animation": { + "duration": 1000 } }, { "add": "annotation", - "method": "symbol", - "target": [ - { - "field": "Brand", - "value": "Ford" - } - ], - "style": { - "icon-url": "http://localhost:3000/icon/rank-1.png", - "width": 20 + "method": "fade", + "target": [], + "animation": { + "duration": 1000 } }, { "add": "annotation", - "method": "circle", + "method": "fill", "target": [ { - "field": "Brand", - "value": "Hyundai" + "field": "funded status", + "value": "Public" } ], "style": { - "width": 30, - "height": 20, - "color": "red" + "color": "#ABABAB" + }, + "animation": { + "duration": 1000 } }, { "add": "annotation", - "method": "texture", + "method": "label", "target": [ { - "field": "Brand", - "value": "Hyundai" + "field": "funded status", + "value": "Public" } - ], "style": { - "background-image": "http://localhost:3000/texture/circle.png" + "text": "3409", + "font-color": "#FF4B19", + "font-size": 20, + "font-weight": "bold", + "font-style": "italic" + }, + "animation": { + "duration": 1000 } } ] diff --git a/src/vis/actions/addimage.js b/src/vis/actions/addimage.js index a46eaa4..e512a22 100644 --- a/src/vis/actions/addimage.js +++ b/src/vis/actions/addimage.js @@ -29,6 +29,7 @@ class AddImage extends Action { let y = 'y' in this._style ? this._style['y'] : 0; let height = 'height' in this._style ? this._style['height'] : 100; let width = 'width' in this._style ? this._style['width'] : 100; + let opacity = 'opacity' in this._style ? this._style['opacity'] : 1; svg.append("svg:image") .attr('x', x) .attr('y', y) @@ -38,7 +39,7 @@ class AddImage extends Action { .attr("opacity", 0) .transition() .duration('duration' in this._animation ? this._animation['duration']: 0) - .attr("opacity", 1); + .attr("opacity", opacity); } } diff --git a/src/vis/charts/areachart/index.js b/src/vis/charts/areachart/index.js index e9a4d86..3a4da6c 100644 --- a/src/vis/charts/areachart/index.js +++ b/src/vis/charts/areachart/index.js @@ -90,28 +90,64 @@ class AreaChart extends Chart { d3.select("#svgBackGrnd").remove() } - if (this.style()['background-color']) { - d3.select("#chartBackGrnd").attr("fill", this.style()['background-color'].color ?? "white").attr("fill-opacity", this.style()['background-color'].opacity ?? 1) - } - else if (this.style()['background-image']) { + if (this.style()['background-image'] || this.style()['background-color']) { let defs = d3.select(container).select("svg").append('svg:defs'); - defs.append("svg:pattern") - .attr("id", "chart-backgroundimage") - .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) + let pattern = defs.append("svg:pattern") + .attr("id", "chart-backgroundimage") + .attr("width", chartbackgroundsize.width) + .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) .attr("patternUnits", "userSpaceOnUse") - .append("svg:image") + + if (this.style()['background-color']) { + pattern.append("svg:rect") + .attr("width",chartbackgroundsize.width) + .attr("height",margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) + .attr("fill", this.style()['background-color'].color ?? "white") + .attr("fill-opacity", this.style()['background-color'].opacity ?? 1) + } + + if (this.style()['background-image']) { + let preserveAspectRatio = "xMidYMid slice" + if (this.style()["background-image"].fit) { + switch (this.style()["background-image"].fit) { + case "fitMid": + preserveAspectRatio = "xMidYMid slice" + break; + case "fitLeft": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitRight": + preserveAspectRatio = "xMaxYMax slice" + break; + case "fitUp": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitDown": + preserveAspectRatio = "xMaxYMax slice" + break; + case "origin": + preserveAspectRatio = "xMidYMid meet" + break; + case "stretch": + preserveAspectRatio = "none" + break; + default: + break + } + } + pattern.append("svg:image") .attr("xlink:href", this.style()["background-image"].url) - .attr("preserveAspectRatio", "xMidYMid slice") + .attr("preserveAspectRatio", preserveAspectRatio) .attr("opacity", this.style()["background-image"].opacity ?? 1) .attr("filter", this.style()["background-image"].grayscale ? "grayscale(" + this.style()["background-image"].grayscale + "%)" : "grayscale(0%)") .attr("width", chartbackgroundsize.width) .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) .attr("x", 0) .attr("y", 0); + } + d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") - } - else { + } else { d3.select("#chartBackGrnd").attr("fill-opacity", 0) } diff --git a/src/vis/charts/barchart/index.js b/src/vis/charts/barchart/index.js index c50093a..bfdc5a3 100644 --- a/src/vis/charts/barchart/index.js +++ b/src/vis/charts/barchart/index.js @@ -184,28 +184,64 @@ class BarChart extends Chart { d3.select("#svgBackGrnd").remove() } - if (this.style()['background-color']) { - d3.select("#chartBackGrnd").attr("fill", this.style()['background-color'].color ?? "white").attr("fill-opacity", this.style()['background-color'].opacity ?? 1) - } - else if (this.style()['background-image']) { + if (this.style()['background-image'] || this.style()['background-color']) { let defs = d3.select(container).select("svg").append('svg:defs'); - defs.append("svg:pattern") - .attr("id", "chart-backgroundimage") - .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) + let pattern = defs.append("svg:pattern") + .attr("id", "chart-backgroundimage") + .attr("width", chartbackgroundsize.width) + .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) .attr("patternUnits", "userSpaceOnUse") - .append("svg:image") + + if (this.style()['background-color']) { + pattern.append("svg:rect") + .attr("width",chartbackgroundsize.width) + .attr("height",margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) + .attr("fill", this.style()['background-color'].color ?? "white") + .attr("fill-opacity", this.style()['background-color'].opacity ?? 1) + } + + if (this.style()['background-image']) { + let preserveAspectRatio = "xMidYMid slice" + if (this.style()["background-image"].fit) { + switch (this.style()["background-image"].fit) { + case "fitMid": + preserveAspectRatio = "xMidYMid slice" + break; + case "fitLeft": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitRight": + preserveAspectRatio = "xMaxYMax slice" + break; + case "fitUp": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitDown": + preserveAspectRatio = "xMaxYMax slice" + break; + case "origin": + preserveAspectRatio = "xMidYMid meet" + break; + case "stretch": + preserveAspectRatio = "none" + break; + default: + break + } + } + pattern.append("svg:image") .attr("xlink:href", this.style()["background-image"].url) - .attr("preserveAspectRatio", "xMidYMid slice") + .attr("preserveAspectRatio", preserveAspectRatio) .attr("opacity", this.style()["background-image"].opacity ?? 1) .attr("filter", this.style()["background-image"].grayscale ? "grayscale(" + this.style()["background-image"].grayscale + "%)" : "grayscale(0%)") .attr("width", chartbackgroundsize.width) .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) .attr("x", 0) .attr("y", 0); + } + d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") - } - else { + } else { d3.select("#chartBackGrnd").attr("fill-opacity", 0) } diff --git a/src/vis/charts/hbarchart/index.js b/src/vis/charts/hbarchart/index.js index a54de8f..59e0a8d 100644 --- a/src/vis/charts/hbarchart/index.js +++ b/src/vis/charts/hbarchart/index.js @@ -179,28 +179,64 @@ class HBarChart extends Chart { d3.select("#svgBackGrnd").remove() } - if (this.style()['background-color']) { - d3.select("#chartBackGrnd").attr("fill", this.style()['background-color'].color ?? "white").attr("fill-opacity", this.style()['background-color'].opacity ?? 1) - } - else if (this.style()['background-image']) { + if (this.style()['background-image'] || this.style()['background-color']) { let defs = d3.select(container).select("svg").append('svg:defs'); - defs.append("svg:pattern") - .attr("id", "chart-backgroundimage") - .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) + let pattern = defs.append("svg:pattern") + .attr("id", "chart-backgroundimage") + .attr("width", chartbackgroundsize.width) + .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) .attr("patternUnits", "userSpaceOnUse") - .append("svg:image") + + if (this.style()['background-color']) { + pattern.append("svg:rect") + .attr("width",chartbackgroundsize.width) + .attr("height",margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) + .attr("fill", this.style()['background-color'].color ?? "white") + .attr("fill-opacity", this.style()['background-color'].opacity ?? 1) + } + + if (this.style()['background-image']) { + let preserveAspectRatio = "xMidYMid slice" + if (this.style()["background-image"].fit) { + switch (this.style()["background-image"].fit) { + case "fitMid": + preserveAspectRatio = "xMidYMid slice" + break; + case "fitLeft": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitRight": + preserveAspectRatio = "xMaxYMax slice" + break; + case "fitUp": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitDown": + preserveAspectRatio = "xMaxYMax slice" + break; + case "origin": + preserveAspectRatio = "xMidYMid meet" + break; + case "stretch": + preserveAspectRatio = "none" + break; + default: + break + } + } + pattern.append("svg:image") .attr("xlink:href", this.style()["background-image"].url) - .attr("preserveAspectRatio", "xMidYMid slice") + .attr("preserveAspectRatio", preserveAspectRatio) .attr("opacity", this.style()["background-image"].opacity ?? 1) .attr("filter", this.style()["background-image"].grayscale ? "grayscale(" + this.style()["background-image"].grayscale + "%)" : "grayscale(0%)") .attr("width", chartbackgroundsize.width) .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) .attr("x", 0) .attr("y", 0); + } + d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") - } - else { + } else { d3.select("#chartBackGrnd").attr("fill-opacity", 0) } diff --git a/src/vis/charts/linechart/index.js b/src/vis/charts/linechart/index.js index 9560720..ff8f6f5 100644 --- a/src/vis/charts/linechart/index.js +++ b/src/vis/charts/linechart/index.js @@ -90,30 +90,66 @@ class LineChart extends Chart { d3.select("#svgBackGrnd").remove() } - if(this.style()['background-color']){ - d3.select("#chartBackGrnd").attr("fill", this.style()['background-color'].color ?? "white").attr("fill-opacity", this.style()['background-color'].opacity ?? 1) - } - else if (this.style()['background-image']){ + if (this.style()['background-image'] || this.style()['background-color']) { let defs = d3.select(container).select("svg").append('svg:defs'); - defs.append("svg:pattern") - .attr("id", "chart-backgroundimage") - .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130*this.Hscaleratio? 500*this.Hscaleratio: chartbackgroundsize.height) + let pattern = defs.append("svg:pattern") + .attr("id", "chart-backgroundimage") + .attr("width", chartbackgroundsize.width) + .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) .attr("patternUnits", "userSpaceOnUse") - .append("svg:image") + + if (this.style()['background-color']) { + pattern.append("svg:rect") + .attr("width",chartbackgroundsize.width) + .attr("height",margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) + .attr("fill", this.style()['background-color'].color ?? "white") + .attr("fill-opacity", this.style()['background-color'].opacity ?? 1) + } + + if (this.style()['background-image']) { + let preserveAspectRatio = "xMidYMid slice" + if (this.style()["background-image"].fit) { + switch (this.style()["background-image"].fit) { + case "fitMid": + preserveAspectRatio = "xMidYMid slice" + break; + case "fitLeft": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitRight": + preserveAspectRatio = "xMaxYMax slice" + break; + case "fitUp": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitDown": + preserveAspectRatio = "xMaxYMax slice" + break; + case "origin": + preserveAspectRatio = "xMidYMid meet" + break; + case "stretch": + preserveAspectRatio = "none" + break; + default: + break + } + } + pattern.append("svg:image") .attr("xlink:href", this.style()["background-image"].url) - .attr("preserveAspectRatio", "xMidYMid slice") + .attr("preserveAspectRatio", preserveAspectRatio) .attr("opacity", this.style()["background-image"].opacity ?? 1) .attr("filter", this.style()["background-image"].grayscale ? "grayscale(" + this.style()["background-image"].grayscale + "%)" : "grayscale(0%)") .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130*this.Hscaleratio? 500*this.Hscaleratio: chartbackgroundsize.height) + .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) .attr("x", 0) .attr("y", 0); - d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") - } - else { + } + + d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") + } else { d3.select("#chartBackGrnd").attr("fill-opacity", 0) - } + } this.initvis(); diff --git a/src/vis/charts/piechart/index.js b/src/vis/charts/piechart/index.js index 2acd0fe..ea1cb32 100644 --- a/src/vis/charts/piechart/index.js +++ b/src/vis/charts/piechart/index.js @@ -111,30 +111,66 @@ class PieChart extends Chart { d3.select("#svgBackGrnd").remove() } - if(this.style()['background-color']){ - d3.select("#chartBackGrnd").attr("fill", this.style()['background-color'].color ?? "white").attr("fill-opacity", this.style()['background-color'].opacity ?? 1) - } - else if (this.style()['background-image']){ + if (this.style()['background-image'] || this.style()['background-color']) { let defs = d3.select(container).select("svg").append('svg:defs'); - defs.append("svg:pattern") - .attr("id", "chart-backgroundimage") - .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130*this.Hscaleratio? 500*this.Hscaleratio: chartbackgroundsize.height) + let pattern = defs.append("svg:pattern") + .attr("id", "chart-backgroundimage") + .attr("width", chartbackgroundsize.width) + .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) .attr("patternUnits", "userSpaceOnUse") - .append("svg:image") + + if (this.style()['background-color']) { + pattern.append("svg:rect") + .attr("width",chartbackgroundsize.width) + .attr("height",margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) + .attr("fill", this.style()['background-color'].color ?? "white") + .attr("fill-opacity", this.style()['background-color'].opacity ?? 1) + } + + if (this.style()['background-image']) { + let preserveAspectRatio = "xMidYMid slice" + if (this.style()["background-image"].fit) { + switch (this.style()["background-image"].fit) { + case "fitMid": + preserveAspectRatio = "xMidYMid slice" + break; + case "fitLeft": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitRight": + preserveAspectRatio = "xMaxYMax slice" + break; + case "fitUp": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitDown": + preserveAspectRatio = "xMaxYMax slice" + break; + case "origin": + preserveAspectRatio = "xMidYMid meet" + break; + case "stretch": + preserveAspectRatio = "none" + break; + default: + break + } + } + pattern.append("svg:image") .attr("xlink:href", this.style()["background-image"].url) - .attr("preserveAspectRatio", "xMidYMid slice") + .attr("preserveAspectRatio", preserveAspectRatio) .attr("opacity", this.style()["background-image"].opacity ?? 1) .attr("filter", this.style()["background-image"].grayscale ? "grayscale(" + this.style()["background-image"].grayscale + "%)" : "grayscale(0%)") .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130*this.Hscaleratio? 500*this.Hscaleratio: chartbackgroundsize.height) + .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) .attr("x", 0) .attr("y", 0); - d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") - } - else { + } + + d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") + } else { d3.select("#chartBackGrnd").attr("fill-opacity", 0) - } + } } /** diff --git a/src/vis/charts/scatterplot/index.js b/src/vis/charts/scatterplot/index.js index 47bc47d..1651264 100644 --- a/src/vis/charts/scatterplot/index.js +++ b/src/vis/charts/scatterplot/index.js @@ -92,28 +92,64 @@ class Scatterplot extends Chart { d3.select("#svgBackGrnd").remove() } - if (this.style()['background-color']) { - d3.select("#chartBackGrnd").attr("fill", this.style()['background-color'].color ?? "white").attr("fill-opacity", this.style()['background-color'].opacity ?? 1) - } - else if (this.style()['background-image']) { + if (this.style()['background-image'] || this.style()['background-color']) { let defs = d3.select(container).select("svg").append('svg:defs'); - defs.append("svg:pattern") - .attr("id", "chart-backgroundimage") - .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) + let pattern = defs.append("svg:pattern") + .attr("id", "chart-backgroundimage") + .attr("width", chartbackgroundsize.width) + .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) .attr("patternUnits", "userSpaceOnUse") - .append("svg:image") + + if (this.style()['background-color']) { + pattern.append("svg:rect") + .attr("width",chartbackgroundsize.width) + .attr("height",margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) + .attr("fill", this.style()['background-color'].color ?? "white") + .attr("fill-opacity", this.style()['background-color'].opacity ?? 1) + } + + if (this.style()['background-image']) { + let preserveAspectRatio = "xMidYMid slice" + if (this.style()["background-image"].fit) { + switch (this.style()["background-image"].fit) { + case "fitMid": + preserveAspectRatio = "xMidYMid slice" + break; + case "fitLeft": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitRight": + preserveAspectRatio = "xMaxYMax slice" + break; + case "fitUp": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitDown": + preserveAspectRatio = "xMaxYMax slice" + break; + case "origin": + preserveAspectRatio = "xMidYMid meet" + break; + case "stretch": + preserveAspectRatio = "none" + break; + default: + break + } + } + pattern.append("svg:image") .attr("xlink:href", this.style()["background-image"].url) - .attr("preserveAspectRatio", "xMidYMid slice") + .attr("preserveAspectRatio", preserveAspectRatio) .attr("opacity", this.style()["background-image"].opacity ?? 1) .attr("filter", this.style()["background-image"].grayscale ? "grayscale(" + this.style()["background-image"].grayscale + "%)" : "grayscale(0%)") .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130 * this.Hscaleratio ? 500 * this.Hscaleratio : chartbackgroundsize.height) + .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) .attr("x", 0) .attr("y", 0); + } + d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") - } - else { + } else { d3.select("#chartBackGrnd").attr("fill-opacity", 0) } // this._svg = d3.select(this.container()) diff --git a/src/vis/charts/unitvis/index.js b/src/vis/charts/unitvis/index.js index aec368b..1191cf6 100644 --- a/src/vis/charts/unitvis/index.js +++ b/src/vis/charts/unitvis/index.js @@ -104,29 +104,65 @@ class Unitvis extends Chart { - if (this.style()['background-color']) { - d3.select("#chartBackGrnd").attr("fill", this.style()['background-color'].color ?? "white").attr("fill-opacity", this.style()['background-color'].opacity ?? 1) - } - else if (this.style()['background-image']) { + if (this.style()['background-image'] || this.style()['background-color']) { let defs = d3.select(container).select("svg").append('svg:defs'); - defs.append("svg:pattern") - .attr("id", "chart-backgroundimage") - .attr("width", 1) - .attr("height", 1) - .attr("patternUnits", "objectBoundingBox") - .append("svg:image") + let pattern = defs.append("svg:pattern") + .attr("id", "chart-backgroundimage") + .attr("width", chartbackgroundsize.width) + .attr("height", margin.top === 130 * this.Hscaleratio ? 505 * this.Hscaleratio : chartbackgroundsize.height) + .attr("patternUnits", "userSpaceOnUse") + + if (this.style()['background-color']) { + pattern.append("svg:rect") + .attr("width",chartbackgroundsize.width) + .attr("height",margin.top === 130 * this.Hscaleratio ? 490 * this.Hscaleratio : chartbackgroundsize.height) + .attr("fill", this.style()['background-color'].color ?? "white") + .attr("fill-opacity", this.style()['background-color'].opacity ?? 1) + } + + if (this.style()['background-image']) { + let preserveAspectRatio = "xMidYMid slice" + if (this.style()["background-image"].fit) { + switch (this.style()["background-image"].fit) { + case "fitMid": + preserveAspectRatio = "xMidYMid slice" + break; + case "fitLeft": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitRight": + preserveAspectRatio = "xMaxYMax slice" + break; + case "fitUp": + preserveAspectRatio = "xMinYMin slice" + break; + case "fitDown": + preserveAspectRatio = "xMaxYMax slice" + break; + case "origin": + preserveAspectRatio = "xMidYMid meet" + break; + case "stretch": + preserveAspectRatio = "none" + break; + default: + break + } + } + pattern.append("svg:image") .attr("xlink:href", this.style()["background-image"].url) - .attr("preserveAspectRatio", "xMidYMid slice") + .attr("preserveAspectRatio", preserveAspectRatio) .attr("opacity", this.style()["background-image"].opacity ?? 1) .attr("filter", this.style()["background-image"].grayscale ? "grayscale(" + this.style()["background-image"].grayscale + "%)" : "grayscale(0%)") .attr("width", chartbackgroundsize.width) - .attr("height", margin.top === 130 * this.scaleratio ? 490 * this.scaleratio : chartbackgroundsize.height) + .attr("height", margin.top === 130 * this.Hscaleratio ? 490 * this.Hscaleratio : chartbackgroundsize.height) .attr("x", 0) .attr("y", 0); + } + d3.select("#chartBackGrnd").attr("fill", "url(#chart-backgroundimage)") - } - else { - d3.select("#chartBackGrnd").remove() + } else { + d3.select("#chartBackGrnd").attr("fill-opacity", 0) }