zoukankan      html  css  js  c++  java
  • angular7 + d3 显示svg

    汇总一些之前没有注意到的问题

    总体思路:

    app只是显示svg为主,接收后端推送的数据改变,显示变化后的svg。

    因此,只用d3的数据绑定更新组件里<svg></svg>节点. 而不用 ng的数据绑定。

    组件view 的svg部分由d3负责。 根据数据service接收到的"不可变数据”,让d3 判断绑定数据的改变,然后去更新view。

    d3的用法类似react 

    selection.data()   类似react的虚拟dom。 enter()  exit() 子集类似diff 处理的callback。

    这样,可以把d3渲染功能封到1个service里。svg的操作部分在web组件里就没有了,在生命周期钩子里调用服务即可。

    定制d3导入子模块,attrs:

    一般用d3 都是:

    import * as d3 from 'd3';

    但是有2个问题:

    1 d3现在特别大,这样import的绝大多数用不上,没必要

    2 d3的子模块太多了,默认并没有把全部子模块都安装上,我很喜欢用的 .attrs()多个属性,就在d3-selection-multi里,默认安装d3是没有安装这个的。

    想用这个,要手工安装

    npm i d3-selection-multi

    d3 官网https://github.com/d3/d3 只给出了node下的导入方式:

    var d3 = Object.assign({}, require("d3-format"), require("d3-geo"), require("d3-geo-projection"));

    在ts里要稍微变一下, 不得不每个命名1次,然后再Object.assign({}

    import * as d3Selection from 'd3-selection';
    import * as d3Attrs from 'd3-selection-multi';
    import * as d3Geo from 'd3-geo';
    export const d3 = Object.assign({}, d3Selection, d3Attrs, d3Geo);

    然后后面就照用了。我用了export导出,可以给别的模块用。

    ng使用d3.select()的渲染时机:

    要在 ngAfterViewInit之后,不然view还没创建好 选不到任何元素。

    svg的style

    参考https://stackoverflow.com/questions/36214546/styles-in-component-for-d3-js-do-not-show-in-angular-2/36214723#36214723

      这个略坑。很多地方给出的解决方案是在组件元数据里设置:

    encapsulation: ViewEncapsulation.None,

    但这样的坏处是,d3.select('svg') 会找到全局全部svg,我恰好全局有多张svg,结果选中了多个组件里的svg。后面的数据绑定到每个svg上去了。(刚开始还怀疑是不是负责d3渲染的service是不是每个组件都要单独注入一个,后来一想这样太傻了,不可能。)

    1 如果设置

    ViewEncapsulation.None
    那么,选中svg元素,就要设置一个id
        this.svg = d3.select(`#${this.name}`);
     
    2如果不设置ViewEncapsulation.None
     那么 默认style没法应用到shallow dom的svg上
    要这样改 组件里的.css 加一行:
    ::ng-deep
    g#marsh path {
        fill: rgb(21, 63, 13);
        fill-opacity: 0.5;
        stroke: rgb(21, 63, 13);
        stroke- 3;
    }

    这样就OK了,个人认为这样最好。

    ——附注:ng7的 ViewEncapsulation 默认是 Emulated。

    MemberDescription
    Emulated: 0

    Emulate Native scoping of styles by adding an attribute containing surrogate id to the Host Element and pre-processing the style rules provided via styles orstyleUrls, and adding the new Host Element attribute to all selectors.

    This is the default option.

    Native: 1  
    None: 2

    Don't provide any template or style encapsulation.

    ShadowDom: 3

    Use Shadow DOM to encapsulate styles.

    For the DOM this means using modern Shadow DOM and creating a ShadowRoot for Component's Host Element.

    默认效果用 ::ng-deep 就够了

    Native在chrome 72上提示,马上要过期

    None 说过了效果,各组件就串了,不推荐

    ShadowDom    好像svg用不了。

  • 相关阅读:
    leetcode[68] Climbing Stairs
    leetcode[67] Plus One
    17_8_16 接口实例化的方法
    17_8_15 lambda 表达式
    17_8_14 回调函数
    17_8_11 Spring Jdbc+Dbcp
    17_8_10 eclipse 中复制网上代码 出现 报错 问题(0)
    17_8_10 PostgreSql Mac
    17_8_10 项目开发流程
    17_8_9 html 不常用的标签
  • 原文地址:https://www.cnblogs.com/xuanmanstein/p/10552428.html
Copyright © 2011-2022 走看看