8

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

 2 years ago
source link: https://my.oschina.net/u/4270927/blog/5294416
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

up-32b70c00b1e9fc20692509ef03017686c1b.png

喜闻乐道的大型电视连续剧《davinci啥时更新》终于在21年初秋迎来了尾声,随之而来的是喜闻乐见的新品datart(数艺)正式发版。这一年,大家可以看到的是群里此起彼伏的这样

奔跑不止,万象更新|datart 蛰伏十月,浴火重生
奔跑不止,万象更新|datart 蛰伏十月,浴火重生

还有这样。。

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

还能这样?

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

未曾看到的,是一个年轻老团队的奔跑不止,一代敏捷大数据的万象更新,话不多说,都在产品里!我们会继续以长青的心、长新的艺,迎接未来与大家共处共进的时光,在大家的审视中前行,在大家的支持中欣喜。


「datart 1.0 alpha」

回顾

时间回到2017年初秋,davinci正式在github开源,初版和二版的davinci主要精力放在如何通过配置化方式可以快速将数据做成所需的图表,以满足配置化可视化的需求。彼时我们借鉴了如superset等优秀的开源项目,希望可以开发出适合国人使用习惯的开源可视化平台,帮助企业敏捷完成“大数据的最后一公里”。

时间来到2018年初秋,davinci第三版横空出世,基本上将davinci第二版完全推倒重做,因为在平台迭代和社区打磨中,我们的想法逐渐发生了变化,我们希望davinci可以支持企业完成“大数据的最后十公里”,不只是用来制作可视化报表,还可以支持制作数据大屏、支持移动端、支持轻数据处理、支持被整合到其他系统中、支持不同团队协同工作等等。基于这样的认知,我们推倒,重来。

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

第三版davinci在社区中取得了巨大的成功,成百上千家企业在生产中使用了davinci,或者二开为其客户提供了产品和服务。同时我们也在不断思索,数据可视化平台的下一站在哪里?

展望

在异世界冒险者的游戏里,每位冒险者都有自己的定位和技能树发展路线,也都有HP(体力值)和MP(魔力值)。数据可视化平台作为一个平台产品,也有自己的产品定位和发展蓝图,也有自己的HP(工程力)和MP(智能力)。数据可视化平台的工程力升级的下一站,是开放化,每个可能扩展的点都应该可插拔化(source、view、chart、viz等),数据可视化平台的智能力升级的下一站,是增强分析,可视化不止局限于看到数据的现状,也可以看到数据的动向。

于是,我们推倒、重来,在2021年初秋,datart孕育而生:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

datart 从产品设计到内核代码全部重写,以一个全新的认知抽象,承载其新的产品使命。初期 datart 会在工程力上迭代拉满,后期会在智能力上探索前行,在开放能力、智能能力、可塑能力上不断增强,打造开源可视化平台的不二首选。

在工具平台产品化的道路上,我们相信“重复的力量”,为了平台产品复用度的不断提升,我们愿意不断推倒重来。未来,datart 会在数据和艺术之间找到最佳平衡点,成为数据冒险者们征服数据异世界的传说级利器。

亮点

可视化

  • 支持单数据图表编辑、样式、设置、计算字段、筛选器、发布、分享、下载等
  • 支持仪表板/大屏编辑、样式、辅助插件、标签页、联动、跳转、控制器、发布、分享、下载等
  • 支持故事板编辑、设置、发布等
  • 支持可扩展插拔新图表组

数据视图

  • 支持视图SQL开发、测试、建模等
  • 支持配置变量、列权限、并发策略

数据源

  • 支持JDBC、FILE、HTTP数据源
  • 支持datart服务端数据聚合
  • 支持可扩展插拔新数据源

定时任务

  • 支持定时邮件发送图表
  • 支持定时微信发送图表

租户权限

  • 支持基于组织租户管理
  • 支持成员邀请、角色管理
  • 支持基于所有资源(可视化/数据视图/数据源/定时任务)的成员/角色细粒度权限管理

体验

部署完成进入系统,首次使用需要注册,点击右下角“注册账号”:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

点击注册之后,会收到确认邮件:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生
奔跑不止,万象更新|datart 蛰伏十月,浴火重生

确认邮件并激活之后,就可以登入系统使用了

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

主导航栏在左侧,首页是可视化目录的展示页面,现在还没有内容,让我们来快速创建一些可视化吧。

点击主导航栏上的“数据源”菜单来创建一个mysql数据源,输入名称、选择数据源类型并填写所需的参数,点击“测试连接”,测试成功之后就可以保存了:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生
奔跑不止,万象更新|datart 蛰伏十月,浴火重生

然后点击主导航栏上的“数据视图”菜单,来编辑一个数据视图。点击数据视图右上角的加号按钮,选择“新建数据视图”, 中部的编辑器会创建一个新的页签:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

在编辑器工具栏中选择刚刚创建的数据源,编写SQL,完成之后点击工具栏上的“执行”按钮,就可以在下方看到执行结果:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

可以点击执行结果列头部的按钮来编辑字段类型和权限,编辑完成后,点击右上角的保存按钮保存数据视图:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

接下来,开始创建数据图表和仪表板,点击主导航栏的“可视化”菜单进入可视化目录,并点击目录右上角的加号进行创建。

我们先创建一个公共数据图表:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生
奔跑不止,万象更新|datart 蛰伏十月,浴火重生

创建完成后,在目录上选中刚创建的数据图表,右侧区域会显示该图表,由于刚创建还没有内容,点击右上角的编辑按钮进行编辑 :

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

进入编辑界面后,在左上角选择刚才创建的数据视图,出现字段之后,将字段拖拽到中间的“数据”栏中来制作图表:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

在中间的“样式”栏中可以编辑图表的显示样式:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

点击右上角保存,一张简单的公共数据图表就制作好了。

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

下面我们来创建一个仪表板,和数据图表的步骤一样,先点击目录右上角的加号,在目录上创建一个仪表板,仪表板可以选择“自动”和“自由”两种布局模式,不同的布局模式适合不同的使用场景;我们先创建一个自动布局的仪表板,同样,创建完成后在目录上选中它,然后在右侧区域点击编辑按钮来进行编辑:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

在编辑界面,我们可以将刚刚创建的公共数据图表添加到仪表板中来,也可以直接在仪表板内创建数据图表:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

一番操作,一个简单仪表板就制作出来了:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

我们可以在左侧目录上选择刚创建的数据图表和仪表板来预览,同时可以在右侧区域顶部点击页签来快速切换:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

接下来我们创建一个故事板,来演示刚刚创建的可视化作品。点击左上角的“演示”菜单,目录会切换为故事板列表,点击加号创建一个故事板,和仪表板一样,创建完成后在右侧点击编辑按钮来制作故事板:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

点击左上角的加号按钮添加刚才创建的仪表板,并设置过渡动画,一个故事版就做好了。点击播放按钮,就可以播放刚才制作好的故事版了:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

以上是 datart 创建可视化作品的一个简单演示,作为一个开源项目,最重要的当然还是它的开放能力,datart 支持用户自定义图表插件,无需重新编译前端代码就可以集成到系统里进行使用,下面介绍怎样简单制作一个自定义图表插件:

首先,我们从选择一个绘图引擎开始,如EChartJS是一个图表绘图引擎,而D3JS则是一个更纯粹的绘图引擎。datart很多图表是基于EChartJS的封装,当然也有很多其他优秀的绘图引擎可以选择,兼收并蓄是datart插件化的核心理念。

一个最基本的插件主要由以下几部分组成:

  • 图表设置配置项(可选项,定制化图形渲染配置以及基于数据视图的配置项)
  • 图表元信息(包含图表名称、图标信息等)
  • 图表依赖类库(第三方资源类库或CSS样式)
  • 图表生命周期函数(datart回调函数,函数中包含Dom Document,当前图表宽高等信息)

接下来,下面我们以D3JS为例来绘制一个散点图:


function D3JSScatterChart() {
    //【可选】扩展配置图表功能,可配合`数据视图`对数据处理
    config: {},

    //【必须】加载D3JS绘图引擎,此处只需给出CDN的链接即可,Datart会负责加载依赖。
    dependency: ['https://d3js.org/d3.v5.min.js'],

    //【必须】设置图表的基本信息,icon可从Datart Icon图标中选取,暂时不支持自定义
    meta: {
      id: 'demo-d3js-scatter-chart',
      name: '[Plugin Demo] D3JS 散点图',
      icon: 'star',
    },

    //【必须】Datart提供的生命周期函数,其他周期如onUpdated,onResize以及onUnMount
    onMount(options, context) {
      // 通过Datart context获取当前的Dom对象     
      const host = context.document.getElementById(options.containerId);
      var margin = { top: 10, right: 40, bottom: 30, left: 30 },
        width = context.width - margin.left - margin.right,
        height = context.height - margin.top - margin.bottom;

      //【以下内容可忽略】基于D3JS的绘制方法
      this.chart = context.window.d3
        .select(host)
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

     // ... 散点图绘图代码已省略,具体参数和使用请参考D3JS手册
  };
}

有了这些基本配置,我们就可以将一个“静态”的散点图显示在datart的图表编辑器界面中并使用了。如果想实现更多高级功能,定制丰富的图表样式、定制基于数据视图的数据配置、定制服务端请求参数,要做到这些需要了解接下来介绍的图表设置配置项(Chart Config)、datart工具类(DHelper)以及生命周期上下文(datart Context),更多配置信息请参考datart用户手册

这里给出注释及完整代码:


/**
 * Datart
 *
 * Copyright 2021
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function D3JSScatterChart({ dHelper }) {
  return {
    config: {
      datas: [
        {
          label: 'metrics',
          key: 'metrics',
          required: true,
          type: 'group',
        },
        {
          label: 'deminsion',
          key: 'deminsion',
          required: true,
          type: 'aggregate',
        },
      ],
      styles: [
        {
          label: 'common.title',
          key: 'scatter',
          comType: 'group',
          rows: [
            {
              label: 'common.color',
              key: 'color',
              comType: 'fontColor',
            },
          ],
        },
      ],
      i18ns: [
        {
          lang: 'zh-CN',
          translation: {
            common: {
              title: '散点图配置',
              color: '气泡颜色',
            },
          },
        },
        {
          lang: 'en',
          translation: {
            common: {
              title: 'Scatter Setting',
              color: 'Bubble Color',
            },
          },
        },
      ],
    },

    isISOContainer: 'demo-d3js-scatter-chart',
    dependency: ['https://d3js.org/d3.v5.min.js'],
    meta: {
      id: 'demo-d3js-scatter-chart',
      name: '[Plugin Demo] D3JS 散点图',
      icon: 'sandiantu',
      requirements: [
        {
          group: [0, 999],
          aggregate: 2,
        },
      ],
    },

    onMount(options, context) {
      if (!context.document) {
        return;
      }

      const host = context.document.getElementById(options.containerId);
      var margin = { top: 10, right: 40, bottom: 30, left: 30 },
        width = context.width - margin.left - margin.right,
        height = context.height - margin.top - margin.bottom;

      // 初始化D3JS绘图区域
      this.chart = context.window.d3
        .select(host)
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
    },

    onUpdated(options, context) {
      if (!options.dataset || !options.dataset.columns || !options.config) {
        return;
      }

      // 获取当前绘图区域的宽高
      const clientWidth = context.window.innerWidth;
      const clientHeight = context.window.innerHeight;
      const margin = { top: 40, right: 40, bottom: 40, left: 40 };
      const width = clientWidth - margin.left - margin.right;
      const height = clientHeight - margin.top - margin.bottom;

      // 获取散点图数据及配置
      const { data, style } = this.getOptions(options.dataset, options.config);

      // 绘制基于百分比的横纵坐标轴散点图, 以下是D3JS绘图逻辑
      var x = context.window.d3
        .scaleLinear()
        .domain([0, 100]) // This is the min and the max of the data: 0 to 100 if percentages
        .range([0, width]); // This is the corresponding value I want in Pixel

      this.chart
        .append('g')
        .attr('transform', 'translate(0,' + height + ')')
        .call(context.window.d3.axisBottom(x));

      // X scale and Axis
      var y = context.window.d3
        .scaleLinear()
        .domain([0, 100]) // This is the min and the max of the data: 0 to 100 if percentages
        .range([height, 0]); // This is the corresponding value I want in Pixel

      this.chart.append('g').call(context.window.d3.axisLeft(y));

      // Add 3 dots for 0, 50 and 100%
      this.chart
        .selectAll('whatever')
        .data(data)
        .enter()
        .append('circle')
        .attr('cx', function (d) {
          return x(d.x);
        })
        .attr('cy', function (d) {
          return y(d.y);
        })
        .style('fill', style.color)
        .attr('r', 7);

      this.chart.selectAll('whatever').style('color', 'blue');
    },

    getOptions(dataset, config) {
      // 当前服务端返回的数据集
      const dataConfigs = config.datas || [];

      // 获取样式配置信息
      const styleConfigs = config.styles;
      const groupConfigs = dataConfigs
        .filter(c => c.type === 'group')
        .flatMap(config => config.rows || []);

      // 获取指标类型配置信息
      const aggregateConfigs = dataConfigs
        .filter(c => c.type === 'aggregate')
        .flatMap(config => config.rows || []);

      // 数据转换,根据Datart提供了Helper转换工具
      const objDataColumns = dHelper.transfromToObjectArray(
        dataset.rows,
        dataset.columns,
      );

      const data = objDataColumns.map(dc => {
        return {
          x: dc[dHelper.getValueByColumnKey(aggregateConfigs[0])],
          y: dc[dHelper.getValueByColumnKey(aggregateConfigs[1])],
        };
      });

      var xMinValue = Math.min(...data.map(o => o.x));
      var xMaxValue = Math.max(...data.map(o => o.y));

      var yMinValue = Math.min(...data.map(o => o.y));
      var yMaxValue = Math.max(...data.map(o => o.y));

      // 获取用户配置
      const color = dHelper.getStyleValueByGroup(
        styleConfigs,
        'scatter',
        'color',
      );

      return {
        style: {
          color,
        },
        data: data.map(d => {
          return {
            x: ((d.x || xMinValue - xMinValue) * 100) / (xMaxValue - xMinValue),
            y: ((d.y || yMinValue - yMinValue) * 100) / (yMaxValue - yMinValue),
          };
        }),
      };
    },
  };
}

最终效果图如下:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

玩转

datart github 下载地址:

https://github.com/running-elephant/datart.git

[email protected]:running-elephant/datart.git

https://github.com/running-elephant/datart/releases/tag/1.0.0-alpha.0

百度网盘:

链接:
https://pan.baidu.com/s/1zW_jsTJk4lYxM6VZDoKGJg

提取码:bzuc

更多跑象科技资讯:

《36氪首发|从实时数据处理服务切入,「跑象科技」完成近千万元天使轮融资》

https://36kr.com/p/1218126964609668

彩蛋,datart主创团队:

奔跑不止,万象更新|datart 蛰伏十月,浴火重生

From 跑象科技

敏捷大数据求

小星星啦~

如果您喜欢我们的平台

就请移步到Github

帮我们点一下Star吧~

您的举手之劳对我们的鼓励

啦!

同时,也欢迎您加入微信群,和技术大神们点对点交流哦~

图片

长按添加加群小助手

烦请告知小助手您的信息来源哦~如:“微信公众号”、“知乎专栏”、“CSDN”、“今日头条”等等~

 长按二维码 一键关注新动向


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK