gojs实用高级用法
本文介绍的是在使用 gojs
制作图的过程中,你可能会碰到的问题的一些解决方案。
gojs 是一个非常强大的可视化关系的js库。
1. 取消更新动画
问题:更新数据的时候,会触发渲染,有渲染动画,用户体验不好。
方案:初始数据绘制,有动画;更新数据绘制,无动画。
代码实现:
// 后面所用到的 diagram 都是 gojs 创建的实例
// diagram_container 为图容器dom id
diagram = $(go.Diagram, 'diagram_container')
方案一:
function updateData (nodeArr = [], linkArr = [], hasAnimation = true ) {
if (hasAnimation) {
diagram.model = new go.GraphLinksModel(nodeArr, linkArr);
} else {
diagram.model.nodeDataArray = nodeArr
diagram.model.linkDataArray = linkArr
}
}
// 初始化实例后处理,只用一次
diagram.animationManager.canStart = function(reason) {
if (reason === 'Model') return false
return true
}
方案二:
// 绑定数据至 diagram,绘制图
function updateData (nodeArr = [], linkArr = [], hasAnimation = true ) {
if (hasAnimation) {
diagram.model = new go.GraphLinksModel(nodeArr, linkArr);
} else {
diagram.model.nodeDataArray = nodeArr
diagram.model.linkDataArray = linkArr
diagram.animationManager.stopAnimation()
}
}
方案三:
// 绑定数据至 diagram,绘制图
function updateData (nodeArr = [], linkArr = [], hasAnimation = true) {
diagram.model = new go.GraphLinksModel(nodeArr, linkArr);
if (diagram.animationManager) {
// Default 有动画,None 没有动画
diagram.animationManager.initialAnimationStyle = hasAnimation ? go.AnimationManager.Default : go.AnimationManager.None;
}
}
2. 导出图(含可视区外的部分)
问题:导出图,利用原生 canvas 相关 api 实现的导出图片,只包含可视区内的
解决:利用 gojs 提供的 api 处理
背后原理:利用数据重新绘制一份图,所有数据节点都在的图可视区内,然后利用原生 canvas 相关 api 实现导出图片
代码实现:
function downloadImg = ({
imgName = 'dag',
bgColor = 'white',
imgType = 'image/png'
}= {}) {
diagram.makeImageData({
scale: 2,
padding: new go.Margin(50, 70),
maxSize: new go.Size(Infinity, Infinity),
background: bgColor,
type: imgType,
returnType: 'blob',
callback: (blob: any) => {
const url = window.URL.createObjectURL(blob)
const fileName = imgName + '.png'
const aEl = document.createElement('a')
aEl.style.display = 'none'
aEl.href = url
aEl.download = fileName
// IE 11
if (window.navigator.msSaveBlob !== undefined) {
window.navigator.msSaveBlob(blob, fileName)
return
}
document.body.appendChild(aEl)
requestAnimationFrame(function() {
aEl.click()
window.URL.revokeObjectURL(url)
document.body.removeChild(aEl)
})
}
})
}
3. 禁用 ctrl 相关快捷键
// 禁用 ctl 相关操作
diagram.commandHandler.doKeyDown = function() {
const e = diagram.lastInput
const control = e.control || e.meta
const key = e.key
// 取消 Ctrl+A/Z/Y/G A-全选、Z-撤销、Y-重做、G-分组
if (control && ['A', 'Z', 'Y', 'G'].includes(key)) return
// 取消 Del/Backspace 删除键
if (key === 'Del' || key === 'Backspace') return
go.CommandHandler.prototype.doKeyDown.call(this)
}
4. 画布滚动模式,无限滚动 or 局部滚动
问题:mac 上 触摸键能左滑右滑控制浏览器页面前进后退,很容易触发
方案:开启无限滚动,避免用户不小心触发了浏览器的前进后退
代码实现:
function infiniteScroll = (infiniteScroll) {
this.diagram.scrollMode = infiniteScroll ? go.Diagram.InfiniteScroll : go.Diagram.DocumentScroll
}
5. 展开收起多层嵌套的组
问题:组多层嵌套,全部展开后,点击单个组收起第一次无效,第二次点击才生效
代码实现:
方式一:nodeArr 没有绑定 展开收起 属性
// groupIds 为所有 group 的ids,从外到内。 一开始遍历组装数据的时候就收集好
// groupIdsReverse 为所有 group 的ids,从内到外
// 全部展开,从外到内
// 全部收起,从内到外
function setExpandCollapse (isExpand, groupIds, groupIdsReverse) {
// 展开和折叠需要从两个方向处理,再次展开折叠交互才正常,否则第一次点无效,需要点第二次材有限
let arr = isExpand ? groupIds : groupIdsReverse;
let group;
arr.forEach(id => {
group = diagram.findNodeForKey(id);
group.isSubGraphExpanded = isExpand;
})
},
方式二:nodeArr 绑定 展开收起 属性 isExpanded
function setExpandCollapse (isExpand) {
const { nodeDataArray, linkDataArray } = diagram.model
const newNodeArr = nodeDataArray.map(v => {
if (v.isGroup) {
return {...v, isExpanded: isExpand}
}
return v
})
// 上面的方法
updateData(newNodeArr, linkArr, false)
}
6. 给图元素加动画
- 虚线动画
- icon loading 旋转动画
代码实现:
function loop = () {
const animationTimer = setTimeout(() => {
clearTimeout(animationTimer)
const oldskips = diagram.skipsUndoManager;
diagram.skipsUndoManager = true;
// 虚线动画
diagram.links.each((link: any) => {
const dashedLinkShape = link.findObject("dashedLink");
if (dashedLinkShape) {
const off = dashedLinkShape.strokeDashOffset - 3;
// 设置(移动)笔划划动画
dashedLinkShape.strokeDashOffset = (off <= 0) ? 60 : off;
}
});
// loading 旋转
diagram.nodes.each((node: any) => {
const loadingShape = node.findObject("loading");
if (loadingShape) {
const angle = loadingShape.angle + 20;
// 设置(移动)笔划划动画
loadingShape.angle = (angle == 0) ? 360 : angle;
}
});
diagram.skipsUndoManager = oldskips;
loop();
}, 180);
}
loop()
7. 修改框选的样式
问题:框选样式:默认是红色的,和自定义的图颜色不匹配
diagram.toolManager.dragSelectingTool.box = $(go.Part,
{ layerName: "Tool", selectable: false },
$(go.Shape,
{ name: "SHAPE", fill: 'rgba(104, 129, 255, 0.2)', stroke: 'rgba(104, 129, 255, 0.5)', strokeWidth: 2 }));
希望对你有帮助,如果有帮助,请点个攒,谢谢!
推荐这些文章:
vue 中的高级用法
1 Mixin 混入的基础语法
1.1 组件 data methods 优先级高于 mixin data 优先级
1.2 生命周期函数先执行 mixin 的再执行组件的
const myMixin = {
data() {
return {
number: 2,
count: 2
}
},
created() {
console.log('mixin created');
},
methods: {
handleClick() {
console.log('maxin handle...
有时候我们希望定义这样一种变量,它的值不能被改变,在整个作用域中都保持固定。例如,用一个变量来表示班级的最大人数,或者表示缓冲区的大小。为了满足这一要求,可以使用const关键字对变量加以限定:
const int MaxNum = 100; //班级的最大人数
这样 MaxNum 的值就不能被修改了,任何对 MaxNum 赋值的行为都将引发错误:
MaxNum = 90; //错误,试图向 const 变量写入数据
我们经常将 const 变量称为常量(Constant)。创建常量的格式通常为:
const type name = value;
const 和 type 都...
参考:https://www.cnblogs.com/caesar-null/p/15228513.html
一、函数返回值,并终止函数
语法: Return表达式;
在函数语句结束时执行,并返回表达式的值作为函数的结果.
二、返回控制语法:return;
一般来讲,为事件处理函数返回return:false。作用在于阻止默认事件行为和取消默认动作,比如,在默认情况下点击一个元素,那么页面就会跳转到语速href属性指定的页面,那当你用return false时,就相当于一个终止符,而return true;就相当于一个执行符。
...
>>>import re>>> pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写>>> m = pattern.match('Hello World Wide Web')>>> print m # 匹配成功,返回一个 Match 对象<_sre.SRE_Match object at 0x10bea83e8>>>> m.group(0) ...
public class Model
{
public int Id { get; set; }
public string Name { get; set; }
}
private static List<Model> LinqIn()
{
List<Model> strList = new List<Model>()
{
new Model(){Id=1,Name = "张三"},
...
背景
在上一篇 巧用滤镜实现高级感拉满的文字快闪切换效果 中,我们提到了一种非常有意思的之前苹果展示文字的动画效果。
本文,会带来另外一个有意思的效果,巧用渐变实现高级感拉满的背景光动画。此效果运用在苹果官网 iPhone 13 Pro 的介绍页中:
实现
这个效果想利用 CSS 完全复制是比较困难的。CSS 模拟出来的光效阴影相对会 Low 一点,只能说是尽量还原。
其实每组光都基本是一样的,所以我们只需要实现其中一组,就几乎能实现了整个效果。
观察这个效果:
它的核心其实就是角向渐变 -- conic-gradient(),利用角向渐变,我们可以大致实现这样一个效果:
<div...
1
这题没有产生闭包
var name="The Window";
var obj={
name:"My Object",
getNameFunc:function(){
return function(){
return this.name;
}
}
}
alert( obj.getNameFunc()() );//The Window
2、、
这题产生了一个闭包
var name2="The Window";
var obj2={
name2:"My Object",
getNameFunc:function(){
...
instanceof
a instanceof A
作用:判断左边这个对象a(实例或属性)是不是右边这个类型(构造函数)A的实例,左边一般是对象的属性或对象的实例,右边一般是构造函数或对象,主要是通过左边的实例的隐式原型属性一直往原型链中找,一直都是通过原型对象的隐式原型属性往原型链中找,右边也通过构造函数的显示原型属性往原型链中找,如果左边和右边都找到尽头了还没有相交的部分,则左边的实例不是右边构造函数的实例,除非他们的原型在原型链中有相交的才相等,相交代表相等。左边是实例,根据隐式原型属性找,右边是对象,根据显示原型属性找,两边各自从自己的方向出发。
1. instanceof是如何判断...
文章链接:https://www.dianjilingqu.com/304.html
本文章来源于网络,版权归原作者所有,如果本站文章侵犯了您的权益,请联系我们删除,联系邮箱:saisai#email.cn,感谢支持理解。