【问题标题】:How to incorporate D3 svg elements into mithril.js?如何将 D3 svg 元素合并到 mithril.js?
【发布时间】:2020-08-12 00:09:15
【问题描述】:

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

到目前为止,我只是将script标签内的JS代码放入我的应用程序中,我知道通常情况下,生成的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 实际上要求我在Modal 的任何子类中实现content() 方法。我查看了Modal.js,相关位是:

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

理想情况下,该解决方案不必覆盖Modalview() 方法,只需在TreeModal 中包含对content() 的更改。

【问题讨论】:

    标签: javascript d3.js svg mithril.js


    【解决方案1】:

    在不了解 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}"/>);
        }
    }
    

    【讨论】:

    • 嗨,Ian,感谢您的解释 - 不幸的是,我注意到我使用的 API 实际上并不建议我更改 view() 方法。我已经编辑了我的帖子以包含我的情况的详细信息;是否仍然可以将 D3 脚本与此对象结构合并?
    • 我以为是因为 modal 有一个 view 方法,所以它是一个秘银组件,但它似乎是在使用 JSX。你是如何尝试在你的秘银应用中使用模态的?
    • 我只想在单击按钮时显示它。 (如果这不能回答你的问题,请告诉我。)我对秘银组件是什么也有点模糊,因为从这个链接 (mithril.js.org/jsx.html) 看起来 JSX 和虚拟节点是使用 m() 创建的可以互换使用吗?
    • @paulinho 对不起,我忘了,你说得对,你可以使用 JSX。如果不查看 Modal 以及如何使用 TreeModal,这很难解决。我已经用其他方法更新了答案。 JSX 未经测试。
    • 这很好用!一个问题:既然oncreate 是在content 之前调用的,那么为什么查找id=this.svgContainerId 对象的行没有失败?那个元素还没有创建吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-13
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    相关资源
    最近更新 更多