diff --git a/package.json b/package.json index dd2e259e..ea8c3cee 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "webpack-cli": "~4.8.0" }, "peerDependencies": { - "jquery": ">=2.0.0", "lodash": ">=4.0.0" }, "dependencies": { diff --git a/src/canvas/baseCanvas.js b/src/canvas/baseCanvas.js index b98d2b9f..539a8bc5 100644 --- a/src/canvas/baseCanvas.js +++ b/src/canvas/baseCanvas.js @@ -1,7 +1,7 @@ 'use strict'; -const $ = require('jquery'); -const _ = require('lodash'); +const $ = require('../utils/tiny-jquery'); +const _ = require('../utils/tiny-lodash'); const domtoimage = require('dom-to-image'); import Canvas from "../interface/canvas"; @@ -190,14 +190,15 @@ class BaseCanvas extends Canvas { this._guideObj = undefined; this._guideTimer = undefined; - + let rootNode = $(this.root) + let rootOffset = rootNode.offset() // 坐标转换服务 this._coordinateService = new CoordinateService({ canvas: this, - terOffsetX: $(this.root).offset().left, - terOffsetY: $(this.root).offset().top, - terWidth: $(this.root).width(), - terHeight: $(this.root).height(), + terOffsetX: rootOffset.left, + terOffsetY: rootOffset.top, + terWidth: rootNode.width(), + terHeight: rootNode.height(), canOffsetX: this._moveData[0], canOffsetY: this._moveData[1], scale: this._zoomData @@ -419,13 +420,14 @@ class BaseCanvas extends Canvas { // 生成svg的wrapper const svg = $(document.createElementNS('http://www.w3.org/2000/svg', 'svg')) - .attr('class', 'butterfly-svg') - .attr('width', _SVGWidth) - .attr('height', _SVGHeight) - .attr('version', '1.1') - .attr('xmlns', 'http://www.w3.org/2000/svg') - .css('z-index', this._dragEdgeZindex) - .appendTo(this.wrapper); + .attr({ + 'class': 'butterfly-svg', + 'width': _SVGWidth, + 'height': _SVGHeight, + 'version': '1.1', + 'xmlns': 'http://www.w3.org/2000/svg' + }).css('z-index', this._dragEdgeZindex) + .appendTo(this.wrapper); if(!_isMobi) { // hack 监听浏览器的缩放比例并适配 @@ -476,13 +478,17 @@ class BaseCanvas extends Canvas { if (_isHightVerChrome && window.ResizeObserver && this.theme.autoResizeRootSize) { // 监听某个dom的resize事件 const _resizeObserver = new ResizeObserver(entries => { - this._rootWidth = $(this.root).width(); - this._rootHeight = $(this.root).height(); + let rootN = $(this.root) + let rootOffset = rootN.offset(); + let rootW = rootN.width(); + let rootH = rootN.height(); + this._rootWidth = rootW; + this._rootHeight = rootH; this._coordinateService._changeCanvasInfo({ - terOffsetX: $(this.root).offset().left, - terOffsetY: $(this.root).offset().top, - terWidth: $(this.root).width(), - terHeight: $(this.root).height() + terOffsetX: rootOffset.left, + terOffsetY: rootOffset.top, + terWidth: rootW, + terHeight: rootH }); this.canvasWrapper.resize({root: this.root}); this.setGridMode(true, undefined , true); @@ -491,13 +497,17 @@ class BaseCanvas extends Canvas { } else { // 降级处理,监控窗口的resize事件 window.addEventListener('resize', () => { - this._rootWidth = $(this.root).width(); - this._rootHeight = $(this.root).height(); + let rootN = $(this.root) + let rootOffset = rootN.offset(); + let rootW = rootN.width(); + let rootH = rootN.height(); + this._rootWidth = rootW; + this._rootHeight = rootH; this._coordinateService._changeCanvasInfo({ - terOffsetX: $(this.root).offset().left, - terOffsetY: $(this.root).offset().top, - terWidth: $(this.root).width(), - terHeight: $(this.root).height() + terOffsetX: rootOffset.left, + terOffsetY: rootOffset.top, + terWidth: rootW, + terHeight: rootH }); this.canvasWrapper.resize({root: this.root}); this.setGridMode(true, undefined, true); @@ -2933,7 +2943,7 @@ class BaseCanvas extends Canvas { ); } }); - } else if (_.isString(_edge)) { + } else if (typeof _edge === 'string') { edgeIndex = _.findIndex(this.edges, (item) => { return _edge === item.id; }); @@ -3118,7 +3128,7 @@ class BaseCanvas extends Canvas { } else { // 重力布局 if (_.get(this.layout, 'type') === 'forceLayout') { - const _opts = $.extend({ + const _opts = _.merge({ // 布局画布总宽度 width, // 布局画布总长度 @@ -3253,7 +3263,7 @@ class BaseCanvas extends Canvas { } }); } else if(_.get(this.layout, 'type') === 'gridLayout') { - const _opts = $.extend({ + const _opts = _.merge({ // 布局画布总宽度 width: _.get(this.layout, 'width') || 150, // 布局画布总长度 @@ -3297,7 +3307,7 @@ class BaseCanvas extends Canvas { }) } } else if(_.get(this.layout, 'type') === 'fruchterman') { - const _opts = $.extend({ + const _opts = _.merge({ // 布局画布总宽度 width, // 布局画布总长度 @@ -3340,7 +3350,7 @@ class BaseCanvas extends Canvas { }) } } else if(_.get(this.layout, 'type') === 'radial') { - const _opts = $.extend({ + const _opts = _.merge({ // 布局画布总宽度 width: _.get(this.layout, 'options.width') || 500, // 布局画布总长度 @@ -3835,8 +3845,7 @@ class BaseCanvas extends Canvas { let _data = this._unionData[name]; if (obj.nodes) { obj.nodes.forEach((item) => { - let isId = _.isString(item); - let node = isId ? this.getNode(item) : item; + let node = typeof item === 'string' ? this.getNode(item) : item; _data.nodes.push(node); }); _data.nodes = _.uniqBy(_data.nodes, 'id'); @@ -3844,8 +3853,7 @@ class BaseCanvas extends Canvas { if (obj.groups) { obj.groups.forEach((item) => { - let isId = _.isString(item); - let group = isId ? this.getGroup(item) : item; + let group = typeof item === 'string' ? this.getGroup(item) : item; _data.groups.push(group); }); _data.groups = _.uniqBy(_data.groups, 'id'); @@ -3853,8 +3861,7 @@ class BaseCanvas extends Canvas { if (obj.edges) { obj.edges.forEach((item) => { - let isId = _.isString(item); - let edge = isId ? this.getEdge(item) : item; + let edge = typeof item === 'string' ? this.getEdge(item) : item; _data.edges.push(edge); }); _data.edges = _.uniqBy(_data.edges, 'id'); @@ -4175,9 +4182,10 @@ class BaseCanvas extends Canvas { } } move(position) { - $(this.wrapper) - .css('left', position[0]) - .css('top', position[1]); + $(this.wrapper).css({ + 'left': position[0], + 'top': position[1] + }); this._coordinateService._changeCanvasInfo({ canOffsetX: position[0], canOffsetY: position[1] diff --git a/src/canvas/treeCanvas.js b/src/canvas/treeCanvas.js index 99073e17..855da0e1 100644 --- a/src/canvas/treeCanvas.js +++ b/src/canvas/treeCanvas.js @@ -1,7 +1,7 @@ 'use strict'; import Canvas from "./baseCanvas"; -const _ = require('lodash'); +const _ = require('../utils/tiny-lodash'); import TreeNode from '../node/treeNode'; import Node from '../node/baseNode'; import Hierarchy from '../utils/layout/hierarchy'; diff --git a/src/edge/baseEdge.js b/src/edge/baseEdge.js index 838e7cb1..ed6a1810 100644 --- a/src/edge/baseEdge.js +++ b/src/edge/baseEdge.js @@ -1,7 +1,7 @@ 'use strict'; -const _ = require('lodash'); -const $ = require('jquery'); +const _ = require('../utils/tiny-lodash'); +const $ = require('../utils/tiny-jquery'); import ArrowUtil from '../utils/arrow'; import * as DrawUtil from '../utils/link'; @@ -181,9 +181,10 @@ class BaseEdge extends Edge { } let labelLenth = length * this.labelPosition + this.labelOffset; let point = this.dom.getPointAtLength(labelLenth); - $(this.labelDom) - .css('left', point.x - this.labelDom.offsetWidth / 2) - .css('top', point.y - this.labelDom.offsetHeight / 2); + $(this.labelDom).css({ + 'left': point.x - this.labelDom.offsetWidth / 2, + 'top': point.y - this.labelDom.offsetHeight / 2 + }); } drawLabel(label) { let isDom = typeof HTMLElement === 'object' ? (obj) => { diff --git a/src/endpoint/baseEndpoint.js b/src/endpoint/baseEndpoint.js index 4535fc2a..486d44a4 100644 --- a/src/endpoint/baseEndpoint.js +++ b/src/endpoint/baseEndpoint.js @@ -1,7 +1,7 @@ -const $ = require('jquery'); -const _ = require('lodash'); +const $ = require('../utils/tiny-jquery'); +const _ = require('../utils/tiny-lodash'); import './baseEndpoint.less'; @@ -88,7 +88,13 @@ class BaseEndpoint extends Endpoint { draw(obj) { let _dom = obj.dom; if (!_dom) { - _dom = $('
').attr('id', this.id); + _dom = $.create({ + tag: 'div', + classNames: ['butterflie-circle-endpoint'], + attr: { + id: this.id + } + }); } else { _dom = $(_dom); } @@ -182,9 +188,7 @@ class BaseEndpoint extends Endpoint { this._posTop += _groupPos.top; this._posLeft += _groupPos.left; } - $(dom) - .css('top', this._top) - .css('left', this._left); + $(dom).css({'top': this._top, 'left': this._left}); this.updated && this.updated(); } diff --git a/src/group/baseGroup.js b/src/group/baseGroup.js index 2b76b3fa..e0279882 100644 --- a/src/group/baseGroup.js +++ b/src/group/baseGroup.js @@ -2,8 +2,8 @@ import './baseGroup.less'; -const $ = require('jquery'); -const _ = require('lodash'); +const $ = require('../utils/tiny-jquery'); +const _ = require('../utils/tiny-lodash'); import Group from '../interface/group'; import Endpoint from '../endpoint/baseEndpoint'; @@ -97,8 +97,10 @@ class BaseGroup extends Group { } let group = $(_dom); - let titleDom = $('
') - .attr('class', 'title'); + let titleDom = $.create({ + tag: 'div', + classNames: ['title'] + }); if (_.get(this, 'options.title')) { titleDom.text(_.get(this, 'options.title')); @@ -232,7 +234,7 @@ class BaseGroup extends Group { } _moveTo(x, y) { // 自身移动 - $(this.dom).css('top', y).css('left', x); + $(this.dom).css({top: y, left: x}); // 节点组的锚点移动 this.endpoints.forEach((item) => { item.moveTo(x - this.left + item._left, y - this.top + item._top); diff --git a/src/node/baseNode.js b/src/node/baseNode.js index 2486c02f..db2be6da 100644 --- a/src/node/baseNode.js +++ b/src/node/baseNode.js @@ -1,5 +1,5 @@ -const $ = require('jquery'); -const _ = require('lodash'); +const $ = require('../utils/tiny-jquery'); +const _ = require('../utils/tiny-lodash'); import Node from '../interface/node'; import Endpoint from '../endpoint/baseEndpoint'; @@ -77,7 +77,7 @@ class BaseNode extends Node { data: endpoint }); - let nodeZindex = $(this.dom).css('z-index'); + let nodeZindex = $(this.dom).style('z-index'); if (nodeZindex !== 'auto') { $(endpoint.dom).css('z-index', Number(nodeZindex) + 1); @@ -151,7 +151,7 @@ class BaseNode extends Node { // drag的时候移动的api _moveTo(x, y) { // 自身移动 - $(this.dom).css('top', y).css('left', x); + $(this.dom).css({top: y, left: x}); // 所在的点移动 this.endpoints.forEach((item) => { item.moveTo(x - this.left + item._left, y - this.top + item._top); diff --git a/src/utils/arrow.js b/src/utils/arrow.js index ec6351ea..44d3bd57 100644 --- a/src/utils/arrow.js +++ b/src/utils/arrow.js @@ -1,5 +1,5 @@ 'use strict'; -import _ from 'lodash'; +import _ from './tiny-lodash'; // todo:丰富箭头样式 let ARROW_TYPE = { diff --git a/src/utils/coordinate.js b/src/utils/coordinate.js index 258d2512..57fe7f54 100644 --- a/src/utils/coordinate.js +++ b/src/utils/coordinate.js @@ -1,6 +1,6 @@ 'use strict'; -const _ = require('lodash'); +const _ = require('./tiny-lodash'); class CoordinateService { constructor(opts) { diff --git a/src/utils/gridService.js b/src/utils/gridService.js index a67d5583..f1192fe2 100644 --- a/src/utils/gridService.js +++ b/src/utils/gridService.js @@ -1,7 +1,7 @@ 'use strict'; -const $ = require('jquery'); -const _ = require('lodash'); +const $ = require('./tiny-jquery'); +const _ = require('./tiny-lodash'); class GridService { constructor(opts) { diff --git a/src/utils/guidelineService.js b/src/utils/guidelineService.js index d7330ff1..b83d2078 100644 --- a/src/utils/guidelineService.js +++ b/src/utils/guidelineService.js @@ -1,7 +1,7 @@ 'use strict'; -const $ = require('jquery'); -const _ = require('lodash'); +const $ = require('./tiny-jquery'); +const _ = require('./tiny-lodash'); class GuidelineService { constructor(opts) { @@ -251,9 +251,10 @@ class GuidelineService { this.clearCanvas(); } move(x, y) { - $(this.dom) - .css('left', x) - .css('top', y); + $(this.dom).css({ + left: x, + top: y + }); this.clearCanvas(); } setOrigin(x, y) { diff --git a/src/utils/layout/dagreLayout.js b/src/utils/layout/dagreLayout.js index ee04b251..db1a1a6b 100644 --- a/src/utils/layout/dagreLayout.js +++ b/src/utils/layout/dagreLayout.js @@ -1,4 +1,5 @@ const dagre = require('dagre'); +const _ = require('../tiny-lodash'); //drage布局 function dagreLayout(param) { const {nodeSize, rankdir, nodesepFunc, ranksepFunc, nodesep, ranksep, controlPoints} = param; @@ -20,14 +21,14 @@ function dagreLayout(param) { if (!nodeSize) { nodeSizeFunc = (d) => { if (d.size) { - if (_.isArray(d.size)) { + if (Array.isArray(d.size)) { return d.size; } return [d.size, d.size]; } return [40, 40]; }; - } else if (_.isArray(nodeSize)) { + } else if (Array.isArray(nodeSize)) { nodeSizeFunc = () => nodeSize; } else { nodeSizeFunc = () => [nodeSize, nodeSize]; diff --git a/src/utils/layout/fishboneLayout.js b/src/utils/layout/fishboneLayout.js index a2a2924c..9ba89a79 100644 --- a/src/utils/layout/fishboneLayout.js +++ b/src/utils/layout/fishboneLayout.js @@ -1,6 +1,6 @@ 'use strict'; -import _ from 'lodash'; +import _ from '../tiny-lodash'; function fishboneLayout(params) { const _biasAngle = _.get(params, 'options.biasAngle', Math.PI / 3); diff --git a/src/utils/layout/fruchterman.js b/src/utils/layout/fruchterman.js index 4f3dbebd..b33c394f 100644 --- a/src/utils/layout/fruchterman.js +++ b/src/utils/layout/fruchterman.js @@ -1,4 +1,5 @@ 'use strict'; +const _ = require('../tiny-lodash') const SPEED_DIVISOR = 800; function fruchterman (param) { const self = param.opts @@ -114,8 +115,8 @@ function fruchterman (param) { } } - // gravity - nodes.forEach((n, j) => { + // gravity + nodes.forEach((n, j) => { if (!_.isNumber(n.x) || !_.isNumber(n.y)) return; const gravityForce = 0.01 * k * gravity; displacements[j].x -= gravityForce * (n.x - center[0]); diff --git a/src/utils/link/link_animate.js b/src/utils/link/link_animate.js index e8cc9767..ea61b5f3 100644 --- a/src/utils/link/link_animate.js +++ b/src/utils/link/link_animate.js @@ -25,7 +25,7 @@ let addAnimate = (targetDom, path, options = {}, animateDom) => { // $(_animateDom).find('animateMotion').attr('path', path); // 为了适配延迟加载的问题,需要重新replaceWith动画标签 let tmpAnimateDom = _animateDom.cloneNode(true); - $(tmpAnimateDom).find('animateMotion').attr('path', path); + $(tmpAnimateDom).find('animateMotion').each((node)=>{node.attr('path', path)}); $(_animateDom).replaceWith(tmpAnimateDom); _animateDom = tmpAnimateDom; } else { diff --git a/src/utils/minimap.js b/src/utils/minimap.js index ce8383ba..2b923c05 100644 --- a/src/utils/minimap.js +++ b/src/utils/minimap.js @@ -1,5 +1,5 @@ -const _ = require('lodash'); -const $ = require('jquery'); +const _ = require('./tiny-lodash'); +const $ = require('./tiny-jquery'); // 每一个dot是一个圆形或者 const DOT_COLOR = 'rgba(246, 105, 2, 1)'; const GROUP_COLOR = 'rgba(61, 86, 92, 1)'; diff --git a/src/utils/scopeCompare.js b/src/utils/scopeCompare.js index 3404a646..ad8a12b1 100644 --- a/src/utils/scopeCompare.js +++ b/src/utils/scopeCompare.js @@ -1,6 +1,6 @@ 'use strict'; -const _ = require('lodash'); +const _ = require('./tiny-lodash'); // 检验scope是否匹配 export default (scope1, scope2, isScopeStrict) => { diff --git a/src/utils/selectCanvas.js b/src/utils/selectCanvas.js index 4d9e5534..b3d622a6 100644 --- a/src/utils/selectCanvas.js +++ b/src/utils/selectCanvas.js @@ -1,6 +1,6 @@ 'use strict'; -const $ = require('jquery'); +const $ = require('./tiny-jquery'); class SelectCanvas { constructor() { diff --git a/src/utils/tiny-jquery.js b/src/utils/tiny-jquery.js new file mode 100644 index 00000000..53e531e2 --- /dev/null +++ b/src/utils/tiny-jquery.js @@ -0,0 +1,518 @@ +/** + * tiny jquery, replace full function jquery + */ + +// 用于停放临时dom的创建 +let tmpDom = document.createElement('div') + +// default easing func: easy in and out +function swing(t) { + return 0.5 - 0.5 * Math.cos(t * Math.PI); +} +/** + * + * @param {*} dom + * dom可以是个 html string + * 也可以是个选择器 + * 还可以是个dom节点 + * @returns + */ +function $(dom) { + if (typeof dom == 'string') { + if (dom[0] == '<') { + // create dom node + tmpDom.innerHTML = dom; + dom = tmpDom.childNodes[0]; + } else { + dom = document.querySelectorAll(dom) + } + } + if (dom instanceof DomNode) { + return dom; + } + let node = { + domNode: dom, + get(index){ + if (Array.isArray(this.domNode)) { + return this.domNode[index]; + } + if (index === 0) { + return this.domNode + } + }, + get length(){ + if (Array.isArray(this.domNode)) { + return this.domNode.length + } else if (this.domNode) { + return 1 + } else { + return 0 + } + } + }; + node.__proto__ = DomNode.prototype; + return node +} + +class DomNode { + constructor(dom) { + this.domNode = domNode + } + /** find有差异 */ + find(node) { + if (node instanceof DomNode) { + node = node.domNode + } + if (typeof node === 'string') { + return $(this.domNode.querySelectorAll(node)); + } else if (node.id){ + return $(this.domNode.querySelectorAll('#'+node.id)); + } else { + let tmpNodes = this.domNode.querySelectorAll(node.tagName + '.' + node.classList.join('.')); + for (let i = 0; i < tmpNodes.length; i++) { + if (tmpNodes[i] === node) { + return $(node) + } + } + return $('') + } + } + insertAfter(dom) { + if (typeof dom === 'string') { + dom = $(dom).domNode + } else if (dom instanceof DomNode) { + dom = dom.domNode + } + let parent = dom.parentNode; + if (dom.nextSibling) { + parent.insertBefore(this.domNode, dom.nextSibling); + } else { + parent.appendChild(this.domNode); + } + } + insertBefore(dom) { + if (typeof dom === 'string') { + dom = $(dom).domNode + } else if (dom instanceof DomNode) { + dom = dom.domNode + } + dom.parentNode.insertBefore(this.domNode, dom) + } + before(){ + + } + after() { + + } + /** + * 将传入的dom append 到当前节点的末尾 + */ + append(dom) { + if (typeof dom === 'string') { + dom = $(dom).domNode; + } else if (dom instanceof DomNode) { + dom = dom.domNode; + } + this.domNode.appendChild(dom); + return this; + } + appendTo(parent) { + if (parent instanceof DomNode) { + parent = parent.domNode; + } + parent.appendChild(this.domNode); + return this; + } + replaceWith(dom) { + if (typeof dom === 'string') { + dom = $(dom).domNode + } + $(dom).insertBefore(this.domNode) + this.remove(); + return this; + } + /** + * 从当前节点的父级移除当前节点 + */ + remove() { + let p = this.domNode.parent; + p.removeChild(this.domNode); + return this; + } + detach() { + return this.remove() + } + /** + * 添加class, 可以是多个参数 + * @param {*} classNames + */ + addClass(className) { + this.domNode.classList.add(...arguments); + return this; + } + /** + * 删除class + * @param {*} classNames + */ + removeClass(className) { + this.domNode.classList.remove(...arguments); + return this; + } + toggleClass(className, bool) { + this.domNode.classList.toggle(className, bool); + return this; + } + /** + * 设置class, 可以是多个参数 + * @param {Array} classNames + */ + setClass(className) { + this.domNode.className = Array.prototype.slice.apply(arguments).join(' '); + return this; + } + /** + * get css properties + * style(key) + * style(k1, k2, k3, k4) + */ + style(key) { + let styles = window.getComputedStyle(this.domNode); + let res = {} + let ll = arguments.length + if (ll === 1) { + return styles.getPropertyValue(key) + } else { + for (let i = 0; i < ll; i++) { + let k = arguments[i]; + res[k] = styles.getPropertyValue(k) + } + return res + } + } + /** + * 设置inline style + * @param {Object} obj + */ + css(obj) { + let ds = this.domNode.style + if (arguments.length == 2) { + let v = arguments[1] + if (typeof v === 'number') { + v += 'px' + } + ds[arguments[0]] = v; + return this; + } else if (arguments.length === 1 && typeof obj == string) { + // get css + this.style(obj); + } else { + for (let i in obj) { + let v = obj[i]; + if (typeof v === 'number') { + v += 'px'; + } + ds[i] = v; + } + return this; + } + } + attr(key, value) { + if (value == undefined) { + if (typeof key === 'string') { + // get attr + this.domNode.getAttribute(key); + } else { + // set attr by obj + for (let k in key) { + this.domNode.setAttribute(k, key[k]); + } + return this; + } + } else { + // set single attr + this.domNode.setAttribute(key, value); + return this; + } + } + /** + * width方法返回的是元素的内容宽度,不包括padding和border。 + * outerWidth方法返回的是元素的内容宽度加上padding和border宽度,不包括margin。 + * outerWidth(true)方法返回的是元素的内容宽度加上padding、border和margin宽度。 + */ + width() { + let elStyles = this.style('paddingLeft', 'paddingRight'); + return this.domNode.clientWidth - parseFloat(elStyles.paddingLeft) - parseFloat(elStyles.paddingRight); + } + height() { + let elStyles = this.style('paddingTop', 'paddingBottom'); + return this.domNode.clientHeight - parseFloat(elStyles.paddingTop) - parseFloat(elStyles.paddingBottom); + } + innerWidth() { + return this.domNode.clientWidth; + } + innerHeight() { + return this.domNode.clientHeight; + } + outerWidth(bool) { + if (bool) { + let elStyles = this.style('marginLeft', 'marginRight'); + return this.domNode.offsetWidth + parseFloat(elStyles.marginLeft) + parseFloat(elStyles.marginRight); + } else { + return this.domNode.offsetWidth + } + } + outerHeight(bool) { + if (bool) { + let elStyles = this.style('marginTop', 'marginBottom'); + return this.domNode.offsetHeight + parseFloat(elStyles.marginTop) + parseFloat(elStyles.marginBottom); + } else { + return this.domNode.offsetHeight + } + } + offsetParent() { + var offsetParent = this.domNode.offsetParent; + + while ( offsetParent && $(offsetParent).style("position") === "static" ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || document.documentElement; + } + /** + * get or set positon of dom + * relative to offsetParent node + */ + position() { + let offsetParent, offset, doc, + elem = this.domNode, + parentOffset = { top: 0, left: 0 }; + + let elemStyles = this.style('position', 'marginTop', 'marginLeft') + // position:fixed elements are offset from the viewport, which itself always has zero offset + if ( elemStyles.position === "fixed" ) { + // Assume position:fixed implies availability of getBoundingClientRect + offset = elem.getBoundingClientRect(); + } else { + offset = this.offset(); + // Account for the *real* offset parent, which can be the document or its root element + // when a statically positioned element is identified + doc = elem.ownerDocument; + offsetParent = elem.offsetParent || doc.documentElement; + while ( offsetParent && + ( offsetParent === doc.body || offsetParent === doc.documentElement ) && + $(offsetParent).style('position') === "static" ) { + offsetParent = offsetParent.parentNode; + } + if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) { + // Incorporate borders into its offset, since they are outside its content origin + parentOffset = $(offsetParent).offset(); + let styles = $(offsetParent).style('borderTopWidth', 'borderLeftWidth') + parentOffset.top += parseFloat(styles.borderTopWidth); + parentOffset.left += parseFloat(styles.borderLeftWidth); + } + } + // Subtract parent offsets and element margins + return { + top: offset.top - parentOffset.top - parseFloat(elemStyles.marginTop), + left: offset.left - parentOffset.left - parseFloat(elemStyles.marginLeft) + }; + } + /** + * absolute offset to page + * get offset of dom + * elem.offset() + * or set offset() + * elem.offset({top: 120, left: 100}) + */ + offset() { + let node = this.domNode; + if (arguments.length == 1) { + let options = arguments[0] + let curOffset = curElem.offset(); + let elemStyles = this.style('top', 'left') + let curCSSTop = parseFloat(elemStyles.top); + let curCSSLeft = parseFloat(elemStyles.left); + let position = elem.style.position; + let calculatePosition = ( position === 'absolute' || position === 'fixed' ) && + ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1; + let curPosition, curTop, curLeft, props = {}; + // Need to be able to calculate position if either + // top or left is auto and position is either absolute or fixed + if ( calculatePosition ) { + curPosition = curElem.position(); + curTop = curPosition.top; + curLeft = curPosition.left; + } else { + curTop = curCSSTop || 0; + curLeft = curCSSLeft || 0; + } + + if ( options.top != null ) { + props.top = ( options.top - curOffset.top ) + curTop; + node.top = props.top + 'px'; + } + if ( options.left != null ) { + props.left = ( options.left - curOffset.left ) + curLeft; + node.left = props.left + 'px'; + } + return this; + } else { + // Return zeros for disconnected and hidden (display: none) elements (gh-2310) + // Support: IE <=11+ + // Running getBoundingClientRect on a + // disconnected node in IE throws an error + if ( !node.getClientRects().length ) { + return { top: 0, left: 0 }; + } + // Get document-relative position by adding viewport scroll to viewport-relative gBCR + let rect = node.getBoundingClientRect(); + let win = node.ownerDocument.defaultView; + return { + top: rect.top + win.pageYOffset, + left: rect.left + win.pageXOffset + }; + } + } + /** + * 绑定事件 + * @param {String} event + * @param {Function(evt)} callback(evt) + * evt {Object} + * - button + - preventDefault() + */ + on(event, callback) { + this.domNode.addEventListener(event, function (evt) { + // TODO prepare event + callback(evt); + }); + return this; + } + /** + * 取消事件监听 + * @param {*} event + * @param {*} callback + */ + off(event, callback) { + let argl = arguments.length; + if (argl <= 1) { + let evts = getEventListeners(this.domNode); + if (!evts) { + return + } + if (argl === 0) { + for (let e in evts) { + evts[e].forEach((handler) => { + this.domNode.removeEventListener(e, handler); + }) + } + } else { + evts[event].forEach((handler) => { + this.domNode.removeEventListener(event, handler); + }) + } + } else { + this.domNode.removeEventListener(event, callback); + } + return this; + } + /** + * + * @param {*} targetProperties + * @param {Number} duration ms + * @param {fn} easingFunction + * @param {fn} callback + $(this.wrapper).animate({ + top: offsetY, + left: offsetX, + }, time, () => { + resolve(); + }); + */ + animate(targetProperties, duration, easing, callback) { + let startValues = {}; + let properties = Object.keys(targetProperties); + properties.forEach((property) => { + startValues[property] = parseFloat(getComputedStyle(element)[property]); + }); + let ll = arguments.length; + if (ll === 1) { + duration = 500; + easing = swing; + } else if (ll === 2) { + easing = swing; + } else if (ll == 3) { + if (typeof easing === 'function') { + callback = easing; + easing = swing; + } + } + // 从毫秒数换算成帧数 + duration = Math.floor(duration / 1000 * 60); // 每秒60帧 + + let startTime = null; + function step(currentTime) { + if (startTime === null) { + startTime = currentTime; + } + let timeElapsed = currentTime - startTime; + let progress = Math.min(timeElapsed / duration, 1); + let easingValue = easingFunction(progress); + properties.forEach((property) => { + let startValue = startValues[property]; + let targetValue = targetProperties[property]; + let currentValue = startValue + (targetValue - startValue) * easingValue; + element.style[property] = `${currentValue}px`; + }); + + if (timeElapsed < duration) { + requestAnimationFrame(step); + } else { + callback && callback(); + } + } + requestAnimationFrame(step); + } + each(fn){ + if (!this.domNode) { + return; + } + this.domNode.forEach((node) => { + fn($(node)); + }); + } +} +/** + * 创建dom节点 + * @param {Object} obj + * tag {String} 标签名字 + * css {Object} + * attr {Object} + * classNames {Array} + * text {String} 节点内容 + * children {Array} + */ +$.create = function (obj) { + let node = $(document.createElement(obj.tag)) + if (obj.css) { + node.css(obj.css); + } + if (obj.attr) { + for (let i in obj.attr) { + node.attr(i, obj.attr[i]); + } + } + if (obj.classNames) { + node.setClass(...obj.classNames) + } + if (obj.text) { + node.domNode.innerText = text; + } + if (obj.children) { + obj.children.forEach((node) => { + node.append(node) + }) + } + return node; +}; + +module.exports = $; diff --git a/src/utils/tiny-lodash.js b/src/utils/tiny-lodash.js new file mode 100644 index 00000000..ad19c5a6 --- /dev/null +++ b/src/utils/tiny-lodash.js @@ -0,0 +1,27 @@ +exports.uniq=require('lodash/uniq'); +exports.uniqBy=require('lodash/uniqBy'); +exports.cloneDeep=require('lodash/cloneDeep'); +exports.find=require('lodash/find'); +exports.findIndex=require('lodash/findIndex'); +exports.get=require('lodash/get'); +exports.isNumber=require('lodash/isNumber'); +exports.isEmpty=require('lodash/isEmpty'); +exports.uniqWith=require('lodash/uniqWith'); +// exports.isArray=require('lodash/isArray'); +exports.isEqual=require('lodash/isEqual'); +exports.isObject=require('lodash/isObject'); +exports.isFunction=require('lodash/isFunction'); +exports.concat=require('lodash/concat'); +exports.flatten=require('lodash/flatten'); +exports.includes=require('lodash/includes'); +exports.differenceBy=require('lodash/differenceBy'); +exports.unionBy=require('lodash/unionBy'); +exports.min=require('lodash/min'); +exports.max=require('lodash/max'); +exports.isNil=require('lodash/isNil'); +exports.debounce=require('lodash/debounce'); +exports.assign=require('lodash/assign'); +exports.merge=require('lodash/merge'); +exports.some=require('lodash/some'); +exports.first=require('lodash/first'); +exports.last=require('lodash/last'); diff --git a/src/utils/toolTip.js b/src/utils/toolTip.js index eebab4ee..eeb88597 100644 --- a/src/utils/toolTip.js +++ b/src/utils/toolTip.js @@ -2,7 +2,7 @@ import './toolTip.less'; -const $ = require('jquery'); +const $ = require('./tiny-jquery'); const DEFUALT = { TEMPLATE: