Я пытаюсь отобразить несколько диаграмм d3 на странице с помощью Rails 7, используя разные идентификаторы div (или svg):
view.html.erb
<%= content_tag "svg", class: 'chart', id: raw(chart_type)+'_'+raw(chart_num), data: {chart_type: chart_type, chart_num: chart_num} do %>
<script>
line('#line_1');
</script>
<% end %>
javascript\компонент\диаграммы\line.js
import * as d3 from "d3";
function line(chart_id) {
const svg = d3.select('#line_1')
.attr('width', 400)
.attr('height', 400)
.style('background-color', 'black');
svg.append(chart_id)
.style("stroke", "lightgreen")
.style("stroke-width", 10)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 200)
.attr("y2", 200);
}
импортная карта.
pin_all_from "app/javascript/components", under: "components"
приложение.js
import "components/charts/line"
Я попробовал предложения из этих постов: Как получить переменную Rails в файл JavaScript (D3) главным образом потому, что идентификатор div/svg — это данные, которые необходимо передать. Кроме того, я знаю, как это сделать с помощью встроенного JavaScript, но не могу понять, как передать идентификатор div в качестве переменной в диаграмму как функцию.
Любая помощь будет принята с благодарностью.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Мне не совсем понятно, о чем вы здесь спрашиваете, но я вижу пару очевидных проблем. Поскольку мы работаем с модулями, функция line не является глобальной, ее необходимо экспортировать/импортировать туда, где это необходимо, или ее нужно явно сделать глобальной.
import * as d3 from "d3";
function line (chart_id) {
const svg = d3.select(chart_id)
.attr('width', 400)
.attr('height', 400)
.style('background-color', 'black');
svg.append("line")
.style("stroke", "lightgreen")
.style("stroke-width", 10)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 200)
.attr("y2", 200);
}
window.line = line;
// or like this
//
// window.line = function (chart_id) {
// ...
// }
Другая проблема заключается в том, что простые теги скриптов загружаются до скриптов модулей, поэтому функция line еще не определена:
<script type = "module">
line("#line_1");
</script>
Возможно, вы захотите создать контроллер Stimulus вместо создания встроенных скриптов и добавления глобальных функций:
https://стимуляциус.hotwired.dev/
$ bin/rails stimulus chart
// app/javascript/controllers/chart_controller.js
import { Controller } from "@hotwired/stimulus"
import * as d3 from "d3";
// Connects to data-controller = "chart"
export default class extends Controller {
// https://stimulus.hotwired.dev/reference/values
static values = {
type: String,
num: Number,
}
connect() {
// this.typeValue
// this.numValue
this.line();
}
line() {
const svg = d3.select(this.element)
.attr('width', 400)
.attr('height', 400)
.style('background-color', 'black');
svg.append("line")
.style("stroke", "lightgreen")
.style("stroke-width", 10)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 200)
.attr("y2", 200);
}
}
# app/views/home/index.html.erb
<%= tag.svg data: {
controller: "chart",
chart_type_value: "line",
chart_num_value: 1
} %>
@ASing Я предполагаю, что ваше значение data1 должно быть определено как объект: data1: Object
это все работает, кроме данных. В div данные помечены
data-chart-data1-valueи представлены в формате json. Вchart_controller.js у меня естьvar data = this.data1Value;, но код d3 для построения линии.attr("d", line(data));шифрует передаваемые данные во что-то непригодное для использования. Любая помощь будет оценена по достоинству.