Как отобразить два графика, сгенерированных из отдельного кода из “observablehq”, в одном окне браузера
Я новичок в d3.js.я скачал два кода, генерирующих графики с сайта “observablehq”. Вот ссылки на коды.
1- масштабируемая-площадь-диаграмма
2-фокус-контекст
Я хочу отобразить оба графика в одном окне браузера. Для этого я поместил файлы в один каталог. Вот html-код масштабируемой области-диаграммы
<!DOCTYPE html> <meta charset="utf-8"> <title>Zoomable Area Chart</title> <link rel="stylesheet" type="text/css" href="./inspector.css"> <body> <script type="module"> import define from "./index.js"; import {Runtime, Library, Inspector} from "./runtime.js"; const runtime = new Runtime(); const main = runtime.module(define, Inspector.into(document.body)); </script>
Вот html-код фокуса-контекста
<!DOCTYPE html> <meta charset="utf-8"> <title>Focus + Context</title> <link rel="stylesheet" type="text/css" href="inspector1.css"> <body> <script type="module"> import define from "./index1.js"; import {Runtime, Library, Inspector} from "./runtime1.js"; const runtime = new Runtime(); const main = runtime.module(define, Inspector.into(document.body)); </script>
Я поместил "фокус + контекст" "скрипт" в html-файл "масштабируемой диаграммы области" следующим образом
<!DOCTYPE html> <meta charset="utf-8"> <title>Zoomable Area Chart</title> <link rel="stylesheet" type="text/css" href="./inspector.css"> <body> <script type="module"> import define from "./index.js"; import {Runtime, Library, Inspector} from "./runtime.js"; const runtime = new Runtime(); const main = runtime.module(define, Inspector.into(document.body)); </script> <script type="module"> import define from "./index1.js"; import {Runtime, Library, Inspector} from "./runtime1.js"; const runtime = new Runtime(); const main = runtime.module(define, Inspector.into(document.body)); </script>
затем я запустил этот html-файл с помощью "webstorm" в браузер. Он не отображает оба графика в одном окне браузера. Он отображает ошибки для первого графика и отображает второй график
URL-адрес изображения
Вот список ошибок первого графика
RuntimeError: md could not be resolved chart = RuntimeError: d3 could not be resolved height = 500 margin = Object {top: 20, right: 20, bottom: 30, left: 30} x = RuntimeError: d3 could not be resolved y = RuntimeError: d3 could not be resolved xAxis = RuntimeError: d3 could not be resolved yAxis = RuntimeError: d3 could not be resolved area = RuntimeError: d3 could not be resolved data = RuntimeError: d3 could not be resolved d3 = RequireError: invalid module
Вот js-файл для "масштабируемой диаграммы области"
// https://observablehq.com/@d3/zoomable-area-chart@212 export default function define(runtime, observer) { const main = runtime.module(); const fileAttachments = new Map([["flights.csv",new URL("./files/1171cb24da0255c434c1ff554b4964c39c1253aa9349f2d356a25351acd3579367f92b24366ae5b6c208c9336811489c0a176cbc0cc62e31feff51e294a178fe",import.meta.url)]]); main.builtin("FileAttachment", runtime.fileAttachments(name => fileAttachments.get(name))); main.variable(observer()).define(["md"], function(md){return( md`# Zoomable Area Chart This zoomable time series area chart shows the number of flights per day. The effect of the September 11, 2001 attacks on air travel is evident.` )}); main.variable(observer("chart")).define("chart", ["d3","margin","width","height","DOM","area","data","x","xAxis","yAxis","y"], function(d3,margin,width,height,DOM,area,data,x,xAxis,yAxis,y) { const zoom = d3.zoom() .scaleExtent([1, 32]) .extent([[margin.left, 0], [width - margin.right, height]]) .translateExtent([[margin.left, -Infinity], [width - margin.right, Infinity]]) .on("zoom", zoomed); const svg = d3.create("svg") .attr("viewBox", [0, 0, width, height]); const clip = DOM.uid("clip"); svg.append("clipPath") .attr("id", clip.id) .append("rect") .attr("x", margin.left) .attr("y", margin.top) .attr("width", width - margin.left - margin.right) .attr("height", height - margin.top - margin.bottom); const path = svg.append("path") .attr("clip-path", clip) .attr("fill", "steelblue") .attr("d", area(data, x)); const gx = svg.append("g") .call(xAxis, x); svg.append("g") .call(yAxis, y); svg.call(zoom) .transition() .duration(750) .call(zoom.scaleTo, 4, [x(Date.UTC(2001, 8, 1)), 0]); function zoomed() { const xz = d3.event.transform.rescaleX(x); path.attr("d", area(data, xz)); gx.call(xAxis, xz); } return svg.node(); } ); main.variable(observer("height")).define("height", function(){return( 500 )}); main.variable(observer("margin")).define("margin", function(){return( {top: 20, right: 20, bottom: 30, left: 30} )}); main.variable(observer("x")).define("x", ["d3","data","margin","width"], function(d3,data,margin,width){return( d3.scaleUtc() .domain(d3.extent(data, d => d.date)) .range([margin.left, width - margin.right]) )}); main.variable(observer("y")).define("y", ["d3","data","height","margin"], function(d3,data,height,margin){return( d3.scaleLinear() .domain([0, d3.max(data, d => d.value)]).nice() .range([height - margin.bottom, margin.top]) )}); main.variable(observer("xAxis")).define("xAxis", ["height","margin","d3","width"], function(height,margin,d3,width){return( (g, x) => g .attr("transform", `translate(0,${height - margin.bottom})`) .call(d3.axisBottom(x).ticks(width / 80).tickSizeOuter(0)) )}); main.variable(observer("yAxis")).define("yAxis", ["margin","d3","data"], function(margin,d3,data){return( (g, y) => g .attr("transform", `translate(${margin.left},0)`) .call(d3.axisLeft(y).ticks(null, "s")) .call(g => g.select(".domain").remove()) .call(g => g.select(".tick:last-of-type text").clone() .attr("x", 3) .attr("text-anchor", "start") .attr("font-weight", "bold") .text(data.y)) )}); main.variable(observer("area")).define("area", ["d3","y"], function(d3,y){return( (data, x) => d3.area() .curve(d3.curveStepAfter) .x(d => x(d.date)) .y0(y(0)) .y1(d => y(d.value)) (data) )}); main.variable(observer("data")).define("data", ["d3","FileAttachment"], async function(d3,FileAttachment){return( Object.assign(d3.csvParse(await FileAttachment("flights.csv").text(), d3.autoType), {y: "Flights"}) )}); main.variable(observer("d3")).define("d3", ["require"], function(require){return( require("d3@5") )}); return main; }
Вот js-файл для "Focus + Context"
// https://observablehq.com/@d3/focus-context@320 export default function define(runtime, observer) { const main = runtime.module(); const fileAttachments = new Map([["aapl.csv",new URL("./files/de259092d525c13bd10926eaf7add45b15f2771a8b39bc541a5bba1e0206add4880eb1d876be8df469328a85243b7d813a91feb8cc4966de582dc02e5f8609b7",import.meta.url)]]); main.builtin("FileAttachment", runtime.fileAttachments(name => fileAttachments.get(name))); main.variable(observer()).define(["md"], function(md){return( md`# Focus + Context This [area chart](/@d3/area-chart) uses brushing to specify a focused area. Drag the gray region to pan, or brush to zoom. Compare to a [zoomable chart](/@d3/zoomable-area-chart). Data: [Yahoo Finance](https://finance.yahoo.com/lookup)` )}); main.variable(observer("chart")).define("chart", ["d3","width","height","DOM","margin","data","xAxis","yAxis","area"], function(d3,width,height,DOM,margin,data,xAxis,yAxis,area) { const svg = d3.create("svg") .attr("viewBox", [0, 0, width, height]) .style("display", "block"); const clipId = DOM.uid("clip"); svg.append("clipPath") .attr("id", clipId.id) .append("rect") .attr("x", margin.left) .attr("y", 0) .attr("height", height) .attr("width", width - margin.left - margin.right); const gx = svg.append("g"); const gy = svg.append("g"); const path = svg.append("path") .datum(data) .attr("clip-path", clipId) .attr("fill", "steelblue"); return Object.assign(svg.node(), { update(focusX, focusY) { gx.call(xAxis, focusX, height); gy.call(yAxis, focusY, data.y); path.attr("d", area(focusX, focusY)); } }); } ); main.variable(observer("viewof focus")).define("viewof focus", ["d3","width","focusHeight","margin","x","xAxis","data","area","y"], function(d3,width,focusHeight,margin,x,xAxis,data,area,y) { const svg = d3.create("svg") .attr("viewBox", [0, 0, width, focusHeight]) .style("display", "block"); const brush = d3.brushX() .extent([[margin.left, 0.5], [width - margin.right, focusHeight - margin.bottom + 0.5]]) .on("brush", brushed) .on("end", brushended); const defaultSelection = [x(d3.utcYear.offset(x.domain()[1], -1)), x.range()[1]]; svg.append("g") .call(xAxis, x, focusHeight); svg.append("path") .datum(data) .attr("fill", "steelblue") .attr("d", area(x, y.copy().range([focusHeight - margin.bottom, 4]))); const gb = svg.append("g") .call(brush) .call(brush.move, defaultSelection); function brushed() { if (d3.event.selection) { svg.property("value", d3.event.selection.map(x.invert, x).map(d3.utcDay.round)); svg.dispatch("input"); } } function brushended() { if (!d3.event.selection) { gb.call(brush.move, defaultSelection); } } return svg.node(); } ); main.variable(observer("focus")).define("focus", ["Generators", "viewof focus"], (G, _) => G.input(_)); main.variable(observer()).define(["focus","d3","data","chart","x","y"], function(focus,d3,data,chart,x,y) { const [minX, maxX] = focus; const maxY = d3.max(data, d => minX <= d.date && d.date <= maxX ? d.value : NaN); chart.update(x.copy().domain(focus), y.copy().domain([0, maxY])); } ); main.variable(observer("data")).define("data", ["d3","FileAttachment"], async function(d3,FileAttachment){return( Object.assign(d3.csvParse(await FileAttachment("aapl.csv").text(), d3.autoType).map(({date, close}) => ({date, value: close})), {y: "↑ Close $"}) )}); main.variable(observer("area")).define("area", ["d3"], function(d3){return( (x, y) => d3.area() .defined(d => !isNaN(d.value)) .x(d => x(d.date)) .y0(y(0)) .y1(d => y(d.value)) )}); main.variable(observer("x")).define("x", ["d3","data","margin","width"], function(d3,data,margin,width){return( d3.scaleUtc() .domain(d3.extent(data, d => d.date)) .range([margin.left, width - margin.right]) )}); main.variable(observer("y")).define("y", ["d3","data","height","margin"], function(d3,data,height,margin){return( d3.scaleLinear() .domain([0, d3.max(data, d => d.value)]) .range([height - margin.bottom, margin.top]) )}); main.variable(observer("xAxis")).define("xAxis", ["margin","d3","width"], function(margin,d3,width){return( (g, x, height) => g .attr("transform", `translate(0,${height - margin.bottom})`) .call(d3.axisBottom(x).ticks(width / 80).tickSizeOuter(0)) )}); main.variable(observer("yAxis")).define("yAxis", ["margin","d3"], function(margin,d3){return( (g, y, title) => g .attr("transform", `translate(${margin.left},0)`) .call(d3.axisLeft(y)) .call(g => g.select(".domain").remove()) .call(g => g.selectAll(".title").data([title]).join("text") .attr("class", "title") .attr("x", -margin.left) .attr("y", 10) .attr("fill", "currentColor") .attr("text-anchor", "start") .text(title)) )}); main.variable(observer("margin")).define("margin", function(){return( {top: 20, right: 20, bottom: 30, left: 40} )}); main.variable(observer("height")).define("height", function(){return( 440 )}); main.variable(observer("focusHeight")).define("focusHeight", function(){return( 100 )}); main.variable(observer("d3")).define("d3", ["require"], function(require){return( require("d3@5") )}); return main; }
Как я могу правильно отображать оба графика в одном окне браузера. Вы можете скачать полный проект с этого сайта ссылка на google Диск
Что я уже пробовал:
Я поместил "фокус + контекст" "скрипт" в html-файл "масштабируемой диаграммы области" следующим образом
<!DOCTYPE html> <meta charset="utf-8"> <title>Zoomable Area Chart</title> <link rel="stylesheet" type="text/css" href="./inspector.css"> <body> <script type="module"> import define from "./index.js"; import {Runtime, Library, Inspector} from "./runtime.js"; const runtime = new Runtime(); const main = runtime.module(define, Inspector.into(document.body)); </script> <script type="module"> import define from "./index1.js"; import {Runtime, Library, Inspector} from "./runtime1.js"; const runtime = new Runtime(); const main = runtime.module(define, Inspector.into(document.body)); </script>