如何将 D3 svg 元素合并到 mithril.js?

How to incorporate D3 svg elements into mithril.js?

我一直在使用 mithril.js 的框架,并希望添加 this script 将交互式树绘制到我网站上的组件中。

到目前为止,我只是将script标签内的JS代码放入我的应用程序中,我知道通常生成的DOM对象是通过调用svg.node()获得的。但是我知道我不能从我的对象的 view 方法中 return,而是需要 return 某种形式的 m(...)。我尝试查看 之类的来源,但无法在其中找到解决我的问题的方法。 是否有将 D3 SVG 图形合并到 mihtril.js 中的已知方法?

如果你想看看我现在的代码:

export default class TreeModal extends Modal {
    content() {

        var treeData = ... // some data

        ... // Other code; irrelevant to this question
        
        var svg = d3.select("body").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom).append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
        
        // Some other code adding more functionality

        // At this point, svg contains the SVG object which I wish to display
        return svg.node(); // Raises ILLEGAL CONSTRUCTOR error; how to adapt this for Mithril.js?
    }
}

在此先感谢您的帮助!

更新: 看来 Modal 对我的问题至关重要,因为我使用的 API 实际上要求我实现 content() 方法在 Modal 的任何子类中。我查看了 Modal.js,相关位是:

export default class Modal {
    view() {
        return (
        <div>
            ...
            {this.content()}
            ...
        </div>
        )
    }
}

理想情况下,解决方案不必重写 Modalview() 方法,而只包含对 TreeModalcontent() 的更改。

如果不了解基本模态的实现或文档,就很难编写正确的代码 class。要解决您提到的 API,我们可以在内容中呈现一个带有随机 ID 的 div,我们稍后在将其放入 DOM 树后使用它来查找它。然后将 SVG 注入 div 并像往常一样使用 D3。我不确定 D3 是否需要清理,但这将在 onremove 中完成,如有必要,请再次确保调用 parents onremove

我在 content 中使用 JSX,但无法测试其格式。

export default class TreeModal extends Modal {
    constructor() {
        // @TODO: Not sure what Modal's constructor looks like.
        super();
        // Create a random DOM id we share between content() 
        //and oncreate().
        this.svgContainerId = 'svg_container_' + 
            Math.floor(Math.random()*1000000000) + 1;
    }
    oncreate(vnode) {
        // @TODO: Check if Modal implements this method or not.
        // super.oncreate(vnode);

        var treeData = {} // some data

        ... // Other code; irrelevant to this question
        
        // USE our predefined id to lookup the div rendered in content
        // and inject our SVG into that container.
        var svg = d3.select(document.getElementById(this.svgContainerId)).append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom).append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
        
        // Some other code adding more functionality
    }
    content() {
        // render a plain DIV with our predefined id that never changes.
        // this JSX is untested
        return (<div id="{this.svgContainerId}"/>);
    }
}