精华内容
下载资源
问答
  • metasfresh 甘特图组件的设计分析 甘特图组件在项目管理,人力资源,和crm模块都有广泛使用,一般使用svg技术来绘制图形,可以按日/周/月/年切换时间单位,也可以手工新增修改拖动任务条 甘特图主要分为任务甘特图...

    metasfresh 甘特图组件的设计分析

    甘特图组件在项目管理,人力资源,和crm模块都有广泛使用,一般使用svg技术来绘制图形,可以按日/周/月/年切换时间单位,也可以手工新增修改拖动任务条

    甘特图主要分为任务甘特图和资源甘特图,一般的甘特图组件实现了任务甘特图,但没有提供资源甘特图的实现,需要自己来实现

    资源甘特图是展示每个资源(产线 设备)的任务安排,以及有关联任务(同属于一个工单)之间的前后关联箭头表示,和任务甘特图每行就一个任务不同的是,资源甘特图每个资源会安排很多任务,任务拖动时,考虑的约束关系更为复杂,既要考虑到资源本身的可用时间的限制,也要考虑到前后任务的时间约束限制

    复杂的甘特图组件,可以考虑使用d3.js库,封装了对svg的操作和对甘特图数据的管理

    展开全文
  • 向日葵甘特图组件

    2008-07-03 19:00:47
    <br> 向日葵甘特图组件完全采用JS实现,与服务器端开发语言无关,可在任何服务器平台上运行; <br> 可轻松地与现有系统整合; 减轻服务器和带宽的负担,节约空间和带宽租用成本; 客户端无需安装...
  • 源自开源的甘特图组件jquery gantt,加上了拖拽和resize功能,enjoy!
  • ## LanePlot-jQuery的甘特图组件 #Description易于使用的甘特图jQuery插件。 Mediworx资助的原始项目 甘特图用于显示一次性事件和基于时间间隔的事件 可用于显示事件冲突,事件链接,时间间隔排序, 或与时间相关...
  • 向日葵甘特图组件1.5版发布后,获得了很多用户的好评。我们也再接再励,对向日葵甘特最近做了如下更新:   1、 增加了甘特图中每个组件的isUsing属性,可以判断其是否加载,从而可以允许用户灵活地显示/隐藏 链接...
  • 支持拖拽的js甘特图组件

    热门讨论 2013-05-30 10:49:15
    源自开源的甘特图组件jquery gantt,加上了拖拽和resize功能,enjoy!
  • AngularJS的甘特图组件 为您的应用程序提供了一个gantt图表组件。 现在试试 现在使用尝试angular-gantt。 还可以使用。 它是针对分支构建的,允许预览前沿功能,但可能非常不稳定。 您甚至可以使用带有 (最新版本...
  • JavaScript实现的甘特图。功能非常强大,应该是商业代码吧,不知道哪里下载的了。如有侵权请告知。
  • 语雀原文 有更好的排版体验~这篇文章主要讲述笔者开发 v-gantt 甘特图组件的经过。起源公司项目有个甘特图的需求。笔者考察了世面上 常见的甘特图组件 后,本着 我上我也行 的心态,以及考虑之前拓展其他开源组件时...

    7b24f47037f1bd85a13c9bf5ec863706.png
    语雀原文 有更好的排版体验~

    这篇文章主要讲述笔者开发 v-gantt 甘特图组件的经过。

    起源

    公司项目有个甘特图的需求。

    笔者考察了世面上 常见的甘特图组件 后,本着 我上我也行 的心态,以及考虑之前拓展其他开源组件时的痛苦体验,决定自研。一番设计后,就开始动工了。

    设计

    布局拆解

    f059b05533b549150ce5ba3ac4c2433a.png

    首先对目标界面进行拆解。可以看到甘特图组件是由 左侧可折叠的树 & 右侧条状图 两部分组成的。

    e6ee3d8bc01662e3690c4af232cd4ac6.png

    滚动方面, 头部日期 header 在横向滚动中应当跟随条状图内容;在纵向滚动中保持固定。 左侧树 组件则相反。考虑到拆解组件时已经将左右侧分离了。所以纵向滚动行为会通过 同步两边纵向滚动容器的 scrollTop 这一 js 技巧来实现。

    0b8d2d500910bb4be530fb2165c22abf.png

    继续拆解右侧条状图组件。可以观察到其由三部分组成:

    1. 日期列表。展示整个甘特图数据的跨越日期范围。此外还负责展示工作日、节假日信息,以及其他的一些高亮信息
    2. 工具栏。放置一些改变视图的操作按钮
    3. 条状图容器。布局条状图节点

    2533f7556595d0aae625f55efb02f2bd.png

    55fd0af3fb74778236640dc497da4b32.png

    继续拆解,我们会发现实质上甘特图有三种节点:

    • 群组节点。包含自身进度状态和若干子节点的节点
    • 叶子节点。没有子节点的节点
    • 里程碑节点。特殊的叶子节点。持续时间仅为一天。只包含 完成 & 未完成 两种状态

    其中群组节点内又是一个布局容器。所以实际实现会有一个递归的处理。

    组件设计

    拆解完布局,也就得到了具体的 vue 组件设计~

    4e5a8bab5437f4503322a46f07a2e879.png

    基本就是 布局拆解 的代码实现。

    数据结构

    定义好组件后,我们需要设计组件所需要的数据结构。这里我们结合 typescript 定义来设计数据分层。

    组件接受的 data 属性类型

    // 首先是传入的总 data,本质是节点的数组
    type GanttPropData = GanttPropNode[]
    
    // 节点共有三种类型
    type GanttPropNode = GanttPropItem | GanttPropGroup | GanttPropMilestone
    
    // 叶子节点类型
    interface GanttPropItem {
      id: string // 唯一标识
      name: string // 名称
      startDate: string // 起始时间
      endDate: string // 结束时间
      progress: number // 0 - 100
    }
    
    // 群组节点类型。基本与叶子节点相同,多一个 children 属性又是一个节点的数组
    // 区别是:起始时间和进度都是可选的。这是因为甘特图内会忽略这些数据,并完全基于其子节点数据生成
    interface GanttPropGroup {
      id: string
      name: string
      startDate?: string
      endDate?: string
      progress?: number
      children: GanttPropData
    }
    
    // 甘特图节点类型
    interface GanttPropMilestone {
      id: string
      name: string
      date: string // 单一日期
      done: boolean // 完成状态
    }
    

    这就是甘特图组件所接收的数据类型。但这里仍缺失群组节点的 持续时间 & 进度状态 数据。所以内部要进行一层转换。

    完整数据

    // 基本数据结构仍相同
    type GanttData = GanttNode[]
    type GanttNode = GanttItem | GanttGroup | GanttMilestone
    
    // 群组节点所有可选项都是必填
    interface GanttGroup {
      id: string
      name: string
      startDate: string
      endDate: string
      progress: number
      children: GanttData
    }
    
    // 其他节点类型完全一致
    type GanttItem = GanttPropItem
    type GanttMilestone = GanttPropMilestone

    可以看到关键转换基本发生在群组节点的数据类型上。下面是核心的 transform & transformGroup 算法。

    function transform(data: GanttPropData): GanttData {
      return data.map((d) => {
        if (isGroup(d)) {
          return transformGroup(d)
        } else if (isMilestone(d)) {
          return transformMilestone(d)
        } else {
          return transformItem(d)
        }
      })
    }
    
    function transformGroup(g: GanttPropGroup): GanttGroup {
      return {
        id: g.id,
        name: g.name,
        children: transform(g.children),
        // 起始时间 = 子节点中最早的起始时间
        get startDate() {
          return this.children.reduce((result, c) => {
            const startDate = isMilestone(c) ? c.date : c.startDate
            return !result || dayjs(startDate).isBefore(result) ? startDate : result
          }, '')
        },
        // 结束时间 = 子节点中最晚的结束时间
        get endDate() {
          return this.children.reduce((result, c) => {
            const endDate = isMilestone(c) ? c.date : c.endDate
            return !result || dayjs(endDate).isAfter(result) ? endDate : result
          }, '')
        },
        // 进度 = 子节点进度的加权平均值(权重 = 持续时间)
        get progress() {
          let finished = 0
          let total = 0
          this.children.forEach((c) => {
            if (isMilestone(c)) return
            const duration = dayjs.$duration(c.startDate, c.endDate)
            finished += duration * c.progress
            total += duration
          })
          return finished / total
        },
      }
    }

    数据准备好了,但要给最终的组件使用还是需要进行数据转换。这里需要产出至少两份数据:

    1. 日期列数据,就是横跨的日期范围,并据此去拿工作日数据
    2. 布局数据

    感兴趣的同学可以去看看源码。这里简要讲讲布局数据的产出

    布局数据

    布局数据,具体来说指的就是一个条状图究的 长度高度 以及 左上角在布局容器中的定位

    我们仍是结合 typescript 定义来分析。

    // 布局数据基础
    interface BaseLayoutItem {
      x: number // 距离容器左边距(列数)
      y: number // 距离容器上边距(行数)
      w: number // 横跨的列数
      h: number // 纵跨的行数
    }
    
    type GanttLayoutData = GanttLayoutNode[]
    type GanttLayoutNode =
      | GanttLayoutLeaf
      | GanttLayoutGroup
      | GanttLayoutMilestone
    interface GanttLayoutLeaf extends BaseLayoutItem {
      progress: number
    }
    interface GanttLayoutGroup extends GanttLayoutLeaf {
      children: GanttLayoutData
    }
    interface GanttLayoutMilestone extends BaseLayoutItem {
      done: boolean
    }

    整个布局数据的结构也是很类似的。其中 progress、done 属性会作为节点的状态来展示

    小结

    至此,只要将节点的定位、状态信息渲染出来,整个甘特图的展示功能就算完成了。接下来就可以进行更复杂的交互功能设计。

    功能设计

    组件间数据共享 & 跨组件通信

    这是所有功能实现的基础。

    有些数据,我们是希望其在每个组件都能访问。可行的方案如下:

    • provide/inject,但在 typescript 环境下缺乏类型提示
    • props & events,但是组件可能嵌套层级较深,比如为了传递一个拖拽事件、一个 rowH 属性,prop 定义和 emit 代码会遍布每一个组件。

    为此,笔者结合这两种做法,实现了下述方案:定义一个会传遍全局的属性(bus),bus 中会存放全局通用的属性,同时包含一个简单的事件发布监听器。

    interface Bus {
      rowH: number // 行高和列宽是每一个布局节点都需要的
      colW: number
    
      ee: EventEmitter
    }
    
    interface EventEmitter {
      on(event: GanttEvent, handler: Function) {}
      emit(event: GanttEvent, ...args: any) {}
    }

    有些同学可能会建议直接传递某个 vue 实例到各个组件,作为全局环境。比如就是根实例。但笔者倾向于定义好清晰的全局数据接口,而不是将根组件完全暴露给所有子组件。这样就不像“公交车”,而是“垃圾场”了。

    有了方便的跨组件通信机制,就可以方便的实现各种功能了。

    树/群组节点折叠实现

    节点折叠,也就是指通过 el-tree 提供的折叠树节点功能,联动实现群组节点折叠的效果。那么关键点就是:

    • 将 el-tree 提供的节点折叠信息,通知到甘特图节点这边
    • 当外部数据发生变更时,已折叠的节点保持它的状态

    两点结合起来,就是要求:

    1. 需要存放折叠好的节点信息,且全局共享
    2. 该信息需要独立存放而不是依附着 GanttData ,否则数据一刷新(每次 GanttPropData 更新都会生成全新的 GanttData )折叠信息就丢失了

    所以,数据定义如下:

    /**
     * key 是节点 id;value 表示是否被折叠
     */
    interface CollapsedMap {
      [id: string]: boolean
    }
    
    // 存放在公交车 bus 上
    interface Bus {
      collapsedMap: CollapsedMap
    }

    具体步骤是:

    1. 监听 el-tree 的折叠事件(node-click),记录该节点是否被折叠
    2. <gantt-group> 组件监听自身的折叠情况 this.bus.collapsedMap[this.data.id] ,决定自身高度以及是否显示子节点们
    3. 每当 GanttData 更新时,对 collapsedMap实现的是增量更新

    // src/index.vue { watch: { // 监听 GanttPropData 的变化 data: { handler(v) { this.collapsedMap = { // 就是提取所有节点的 key,一个类似 flatmap 的过程,初始 val 都是 false ...getCollapsedMap(v), // 优先保留折叠状态 ...this.collapsedMap, } }, immediate: true, }, }, }

    拖拽实现

    这是一个比较重头的功能。

    首先是需求定义:

    1. 甘特图节点可以整体被鼠标拖拽;叶子节点还可以拖拽其右侧实现长度更改功能
    2. 拖拽时,应限定方向在水平方向
    3. 拖拽时,条状图应当有相应移位和形变(感觉跟手)
    4. 结束拖拽时,甘特图保持状态,并通知外界

    因为通知外界只需要用我们之前定义的 bus.ee 事件监听发布器即可实现,所以我们要解决的是:

    1. 监听拖拽事件发生
    2. 监听时,改变节点的布局信息

    可选的拖拽实现如下:

    1. drag & drop event。但不支持限定方向;不支持自定义 cursor 样式
    2. mouse event 系列。支持细粒度地模拟拖拽,没有 drag & drop 的限制
    3. 第三方拖拽库。只能说一方面坑的很;另一方面,当你真正理解所需要的功能时,代码实现并不多

    在数据结构定义的章节笔者提过,节点的布局信息是由 GanttLayoutData 决定的。实际并不准确:真实的定位样式,是需要额外结合 拖拽信息(dragData & resizeData)实现。也就是:

    • 节点的左边距 x = layoutData.x + dragData.offsetX
    • 节点的长度 w = layoutData.w + resizeData.offsetX

    其中 dragData & resizeData 的实现是:

    1. 在节点的 mousedown 事件初始化(offsetX = 0)
    2. 在节点的 mousemove 事件变更(offsetX += event.movementX)
    3. 在节点的 mousedown 事件,如果发生了实质变更,则通过 bus.ee.emit 发送变更

    更具体的信息,可以参考 src/components/gantt-node.vue 源码

    快速定位功能

    简单来说,就是点击 今天 按钮,今天列跳转到视窗内;点击 树节点 ,对应的条状图节点出现在视窗内。

    第一反应是利用浏览器内置的 scrollToView api 实现。事实上跳转到今天列功能就是这样实现的。

    但后一种联动要复杂一些。条状图节点是通过 transform: translate 绝对定位的节点,再加上先前在 布局拆解 阶段提及的两种滚动行为实现,导致 scrollToView 不能满足我们的需求。

    那么剩下的方案,就是手动控制 横向滚动容器的 scrollLeft纵向滚动容器的 scrollTop

    具体操作是:

    1. 监听树节点的 click 事件,通过 bus.ee.emit 发送 ScrollToNodeEvent ,携带节点 id
    2. 所有 <gantt-node> 组件都会监听该事件。当发现事件 id 与自身 id 匹配时,通过 bus.ee.emit 发送 ScrollToEvent ,携带自身在 顶级 <gantt-layout> 容器中的位置。注意这里需要递归往上累积计算
    3. <gantt-chart> 组件(掌控着两个滚动容器的位置)监听 ScrollToEvent ,调整两个滚动容器的 scrollTop & scrollLeft 值

    哇,三言两语就说完了呢~ 实际开发的时候踩了不少坑 (特别是折磨在 drag & drop api 上)

    具体实现

    这一部分,感兴趣的朋友就可以 参考源码 啦~ 也可以直接通过社交平台(github)的 issue & pr 功能与笔者交流。

    结语

    这次历时三周的开发,让笔者体会到设计先行对代码质量的提升。核心体验就是开发是遵照着目标前进的,可以专心于逻辑的同时保持组件设计分工的稳定。

    另外,架构是且应当是不断演进的。不同的功能复杂度适合不同的架构复杂度。事实上,就跨组件通信机制而言组件内部就重构了一两次。但笔者认为这些劳动都是值得的。只有抱着 架构应当持续演进 的心态,就能保持好随时 微重构 的心态,保持对添加新功能的信息~ 。最后再借《反脆弱》一书的核心论点论证:一个貌似稳定的系统其实是畏惧变化、僵死且具有脆弱性的系统;一个貌似反复变更、时不时破坏重建的系统,则是能够不断演进,持续变强。

    感谢阅读!

    展开全文
  • Vue.js的简单易用的甘特图组件 主页 安装 您可以使用npm在项目中安装和使用Vue-Ganttastic: npm install vue-ganttastic 是Vue-Ganttastic的对等依赖项。 为了使Vue-Ganttastic正常工作,您需要在项目中安装它:...
  • 参考最近一段时间客户所提问题和需求,清明时节时我们对甘特图进行了集中更新,发布了向日葵甘特图组件1.1版。 向日葵甘特图组件1.1版完善了以下几点:1、对甘特图的任务移动功能进行重新整理,重新实现上移和下移...

    参考最近一段时间客户所提问题和需求,清明时节时我们对甘特图进行了集中更新,发布了向日葵甘特图组件1.1版。

    向日葵甘特图组件1.1版完善了以下几点:
    1、对甘特图的任务移动功能进行重新整理,重新实现上移和下移,使数据API更加清晰;
    2、对甘特图拖动过程之中的内存进行优化,避免频繁的拖动造成内存泄漏的情况;
    3、对甘特图的折叠功能进行优化,避免折叠过程调用无关数据的现象,提升折叠的性能;
    4、对箭头的显示进行优化,箭头只在两个任务都下载完成之后才会显示,避免因为任务的链接关系而导致数据被大量下载的情况;
    4、为SFData和SFGantt提供depose方法,用来销毁,节省内存

    可参看示例:

    http://www.51diaodu.cn/sfgantt/examples/SFGantt/depose.htm
    5、解决在最后的空白行右键单击的时候无法在最后一行添加任务的BUG;
    6、提供在配置文件之中配置版权信息的方式
    7、解决时间控件输入后的键盘捕捉问题,
    这属于js Calendar组件的一个小bug,需要先将其hide再销毁。

    8、对任务联动的范例进行优化

    gantt图修改了一下机制,可以批量对任务进行update。

    任务拖动后的联动效果比以前好了许多,可参看示例:

    http://www.51diaodu.cn/sfgantt/examples/SFProject/automove1.htm
    9、可以禁止用户拖动右下角箭头改变甘特图大小。

    http://www.51diaodu.cn/sfgantt/examples/SFGantt/setmaxsize.htm

     

     

    线上还新增了一栏向日葵项目管理,下一阶段我们会逐渐在web 上实现Ms Project的基本功能。

    向日葵项目管理将会采用完全开源的方式,其宗旨是提供一个完整的使用甘特图组件应用范例,从而达到推广甘特组件的目的。

    向日葵项目管理采用了OpenId登录模式,用户只需要用友google/gmail,hotmail/msn,yahoo,校内网的账户就可以直接使用。

    转载于:https://www.cnblogs.com/tidestone/archive/2009/04/08/1431336.html

    展开全文
  • 关键字:甘特图,Flash甘特图,AnyGantt,项目管理 AnyGantt是一个强大的,基于Flash的数据可视化解决方案。允许任何人利用有力的动画和最终的可交互性。 AnyGantt是构建复杂和翔实的甘特图的理想工具。 AnyGantt...

    关键字:甘特图,Flash甘特图,AnyGantt,项目管理

     

     

    AnyGantt是一个强大的,基于Flash的数据可视化解决方案。允许任何人利用有力的动画和最终的可交互性。 AnyGantt是构建复杂和翔实的甘特图的理想工具。

    AnyGantt是完全跨浏览器和跨平台的。它可用于ASP.NET,ASP,PHP,JSP,ColdFusion,Ruby on RailsAnyGantt,简单的HTML页和PowerPoint演示文稿。AnyGantt使用XML作为通用数据接口,所以你可以从任何仓库显示数据:从文本文件,Excel,CSV格式到MySQL,MS SQL和Oracle数据库服务器。

    没有必要有任何Flash的技能或知识,使用您所选择的服务器或桌面平台创建应用程序---AnyGantAnyGanttt解决方案将注意图表。如果您需要先进的,屡获殊荣的甘特图,那么AnyGantt是为您提供的完美解决方案。
    AnyGanttAnyGanttAnyGantt

     

    人力资源图
    人力资源图


    面向活动的图表
    面向活动的图表


    简单的甘特图
    简单的甘特图


    基线图
    基线图


    资源甘特图
    资源甘特图


    原文来自 http://www.fanganwang.com/product/1455

    转载于:https://www.cnblogs.com/busyant/p/3674995.html

    展开全文
  • 向日葵甘特图组件增加了几个新特性: 1、可以通过设置task的hyperlink属性为每个任务建立超级链接, 2、可以设置甘特图组件的readonly模式,可参看示例...
  • Twproject Gantt 是一款基于 jQuery 开发的甘特图组件,也可以创建其它图表,例如任务树(Task Trees)。内置编辑、缩放和 CSS 皮肤等功能。更重要的是, 它是免费开源的。
  • AnyGantt是构建复杂和翔实的甘特图的理想工具。AnyGantt是完全跨浏览器和跨平台的。它可用于ASP.NET,ASP,PHP,JSP,ColdFusion,Ruby on RailsAnyGantt,简单的HTML页和PowerPoint演示文稿。AnyGan...
  • Flex甘特图组件

    2012-08-21 12:00:21
    原文来自方案网 http://www.fanganwang.com/Product-detail-item-1455.html,欢迎转载。 关键字:甘特图,Flash甘特图,AnyGantt,项目管理 AnyGan...
  • AnyGantt是构建复杂和翔实的甘特图的理想工具。 AnyGantt是完全跨浏览器和跨平台的。它可用于ASP.NET,ASP,PHP,JSP,ColdFusion,Ruby on RailsAnyGantt,简单的HTML页和PowerPoint演示文稿。AnyGantt使用XML...
  • 完全免费JS网络计划部件dhtmlxgantt 安裝 可应用NuGet、Bower、npm包管理工具安裝(运用在asp.net、nodejs等新项目上)。 Nuget nuget install DHTMLX.Gantt npm npm install dhtmlx-gantt 或应用CDN、...
  • AnyGantt Flash甘特图组件

    千次阅读 2014-04-19 14:41:56
    AnyGantt是构建复杂和翔实的甘特图的理想工具。 AnyGantt是完全跨浏览器和跨平台的。它可用于ASP.NET,ASP,PHP,JSP,ColdFusion,Ruby on Rails,简单的HTML页和PowerPoint演示文稿。AnyGantt使用XML作为通用...
  • 基于AJAX的向日葵甘特图组件2008-7-20发布了Beta2版,可在客户端动态加载10,000个任务,支持IE5.5/6/7,Firefox2/3,Opera 9.5等多种主流浏览器,欢迎大家在http://www.51diaodu.cn/下载体验!且请 见多识广的各位...
  • 使用Edo.lists.Gantt创建的甘特图组件,只是一个条形图视图。 一般人们需要的甘特图,是一个左侧树,右侧条形图的视图。 EdoJS提供了一个强大的树形组件:Edo.lists.Tree,来帮助我们实现一个标准的甘特图。 ...
  • 如果您需要先进的,屡获殊荣的甘特图,那么AnyGantt是为您提供的完美解决方案。 人力资源图原文来自龙博方案网 http://www.fanganwang.com/product/1455   面向活动的图表 简单的甘特图 基线图 资源甘特图 ...
  • AnyGantt是构建复杂和翔实的甘特图的理想工具。 AnyGantt是完全跨浏览器和跨平台的。它可用于ASP.NET,ASP,PHP,JSP,ColdFusion,Ruby on Rails,简单的HTML页和PowerPoint演示文稿。AnyGantt使用XML作为通用...
  • 使用Edo.lists.Gantt创建的甘特图组件,只是一个条形图视图。 一般人们需要的甘特图,是一个左侧树,右侧条形图的视图。 EdoJS提供了一个强大的树形组件:Edo.lists.Tree,来帮助我们实现一个标准的甘特图。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,408
精华内容 1,763
关键字:

甘特图组件