Передайте идентификатор div в функцию javascript, чтобы отобразить несколько диаграмм d3 на странице

Я пытаюсь отобразить несколько диаграмм 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 в качестве переменной в диаграмму как функцию.

Любая помощь будет принята с благодарностью.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мне не совсем понятно, о чем вы здесь спрашиваете, но я вижу пару очевидных проблем. Поскольку мы работаем с модулями, функция 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
} %>

это все работает, кроме данных. В div данные помечены data-chart-data1-value и представлены в формате json. Вchart_controller.js у меня есть var data = this.data1Value;, но код d3 для построения линии .attr("d", line(data)); шифрует передаваемые данные во что-то непригодное для использования. Любая помощь будет оценена по достоинству.

ASing 20.03.2024 23:35

@ASing Я предполагаю, что ваше значение data1 должно быть определено как объект: data1: Object

Alex 20.03.2024 23:43

Другие вопросы по теме