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

问题描述

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

到目前为止,我只是将JS代码放在script标记内的应用程序中,并且我知道通常情况下,生成的DOM对象是通过调用svg.node()获得的。但是我知道我无法从对象的view方法返回该值,而是需要返回m(...)形式的值。我尝试查看this one之类的资源,但是找不到解决我问题的方法是否存在将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>
        )
    }
}

理想情况下,该解决方案不必覆盖view()的{​​{1}}方法,而只需在Modal中包含对content()的更改。

解决方法

在不知道基本Modal类的实现或文档的情况下,很难编写正确的代码。要解决您提到的API,我们可以在内容中呈现一个带有随机ID的div,稍后将其放入DOM树中后再用于查找它。然后将SVG注入该div中,然后像往常一样使用D3。我不确定D3是否需要清理,但是可以在onremove中完成,如果有必要,请再次确保致电父母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}"/>);
    }
}