amchart Paper源码阅读- 03/17/2023

102 阅读2分钟

Simple Concepts

SVGElement

image.png

HTMLElement

image.png

SVG

// Create SVG group to hold everything in
this.group = this.paper.addGroup("g");

SVG Element

/**
 * Represents available SVG elements that can be added to paper.
 * 同时上述link,可以去查看具体的分类
 */
export type SVGElementNames = "a" | "altGlyph" | "altGlyphDef" | "altGlyphItem" | "animate"
 | "animateColor" | "animateMotion" | "animateTransform" 
| "circle" | "clipPath" | "color-profile" | "cursor" | "defs" | "desc" | "ellipse" | "feBlend" | 
"feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting"
 | "feDisplacementMap" | "feDistantLight" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR"
  | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight"
   | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "feConvolveMatrix" | "filter" | 
   "font" | "font-face" | "font-face-format" | "font-face-name" | "font-face-src" | "font-face-uri" | 
   "foreignObject" | "g" | "glyph" | "glyphRef" | "hkern" | "image" | "line" | "linearGradient" | 
   "marker" | "mask" | "metadata" | "missing-glyph" | "mpath" | "path" | "pattern" | "polygon" | "polyline" 
   | "radialGradient" | "rect" | "script" | "set" | "stop" | "style" | "svg" | "switch" | "symbol" | "text" 
   | "textPath" | "title" | "tref" | "tspan" | "use" | "view" | "vkern";

SVG Attributes

/**
 * Defines available SVG attributes.
 */
export type SVGAttribute =
	"accent-height" | "accumulate" | "additive" | "alignment-baseline" | "allowReorder" 
	| "alphabetic" | "amplitude" | "arabic-form" | "aria-checked" | "aria-describedby" 
	| "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-controls" 
	| "aria-orientation" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" 
	| "aria-valuetext" | "ascent" | "attributeName" | "attributeType" | "autoReverse" 
	| "azimuth" | "baseFrequency" | "baseline-shift" | "baseProfile" | "bbox" | "begin"
	| "bias" | "by" | "calcMode" | "cap-height" | "class" | "clip" | "clipPathUnits" 
	| "clip-path" | "clip-rule" | "color" | "color-interpolation" | "color-interpolation-filters"
	| "color-profile" | "color-rendering" | "contentScriptType" | "contentStyleType" | "cursor"
	| "cx" | "cy" | "d" | "decelerate" | "descent" | "diffuseConstant" | "direction" | "display" 
	| "divisor" | "dominant-baseline" | "dur" | "dx" | "dy" | "edgeMode" | "elevation" 
	| "enable-background" | "end" | "exponent" | "externalResourcesRequired" | "fill" 
	| "fill-opacity" | "fill-rule" | "filter" | "filterRes" | "filterUnits" | "flood-color"
	| "flood-opacity" | "focusable" | "font-family" | "font-size" | "font-size-adjust" 
	| "font-stretch" | "font-style" | "font-variant" | "font-weight" | "format" | "from"
	| "fx" | "fy" | "g1" | "g2" | "glyph-name" | "glyph-orientation-horizontal" 
	| "glyph-orientation-vertical" | "glyphRef" | "gradientTransform" | "gradientUnits" 
	| "hanging" | "height" | "href" | "horiz-adv-x" | "horiz-origin-x" | "id" | "ideographic" 
	| "image-rendering" | "in" | "in2" | "intercept" | "k" | "k1" | "k2" | "k3" | "k4" 
	| "kernelMatrix" | "kernelUnitLength" | "kerning" | "keyPoints" | "keySplines" | "keyTimes" 
	| "lang" | "lengthAdjust" | "letter-spacing" | "lighting-color" | "limitingConeAngle" | "local" 
	| "marker-end" | "marker-mid" | "marker-start" | "markerHeight" | "markerUnits" | "markerWidth" 
	| "mask" | "maskContentUnits" | "maskUnits" | "mathematical" | "max" | "media" | "method" | "min" 
	| "mode" | "name" | "numOctaves" | "offset" | "onabort" | "onactivate" | "onbegin" | "onclick" 
	| "onend" | "onerror" | "onfocusin" | "onfocusout" | "onload" | "onmousedown" | "onmousemove" 
	| "onmouseout" | "onmouseover" | "onmouseup" | "onrepeat" | "onresize" | "onscroll" | "onunload" 
	| "onzoom" | "opacity" | "operator" | "order" | "orient" | "orientation" | "origin" | "overflow" 
	| "overline-position" | "overline-thickness" | "panose-1" | "paint-order" | "pathLength" 
	| "patternContentUnits" | "patternTransform" | "patternUnits" | "pointer-events" | "points" 
	| "pointsAtX" | "pointsAtY" | "pointsAtZ" | "preserveAlpha" | "preserveAspectRatio" | "primitiveUnits" 
	| "r" | "radius" | "refX" | "refY" | "rendering-intent" | "repeatCount" | "repeatDur" | "requiredExtensions" 
	| "requiredFeatures" | "restart" | "result" | "role" | "rotate" | "rx" | "ry" | "scale" | "seed" | "shape-rendering" 
	| "slope" | "spacing" | "specularConstant" | "specularExponent" | "speed" | "spreadMethod" | "startOffset" 
	| "stdDeviation" | "stemh" | "stemv" | "stitchTiles" | "stop-color" | "stop-opacity" | "strikethrough-position" 
	| "strikethrough-thickness" | "string" | "stroke" | "stroke-dasharray" | "stroke-dashoffset" | "stroke-linecap" 
	| "stroke-linejoin" | "stroke-miterlimit" | "stroke-opacity" | "stroke-width" | "style" | "surfaceScale" 
	| "systemLanguage" | "tabindex" | "tableValues" | "target" | "targetX" | "targetY" | "text-anchor" | "text-decoration" 
	| "text-rendering" | "textLength" | "to" | "transform" | "type" | "u1" | "u2" | "underline-position" 
	| "underline-thickness" | "unicode" | "unicode-bidi" | "unicode-range" | "units-per-em" | "v-alphabetic"
	| "v-hanging" | "v-ideographic" | "v-mathematical" | "values" | "version" | "vert-adv-y" | "vert-origin-x" 
	| "vert-origin-y" | "viewBox" | "viewTarget" | "visibility" | "width" | "widths" | "word-spacing" | "writing-mode" 
	| "x" | "x-height" | "x1" | "x2" | "xChannelSelector" | "xlink:actuate" | "xlink:arcrole" | "xlink:href" | "xlink:role" 
	| "xlink:show" | "xlink:title" | "xlink:type" | "xml:base" | "xml:lang" | "xml:space" | "y" | "y1" | "y2" 
	| "yChannelSelector" | "z" | "zoomAndPan";

创建SVG标签元素

constructor(container: HTMLElement, id: string) {

	//html dom对象传入
	this.container = container;
	this.id = id;

	// 创建一个符合svg规范的标识位svg的元素,并作为子元素
	let svg = <SVGSVGElement>document.createElementNS($dom.SVGNS, "svg");
	svg.setAttribute("version", "1.1");
	svg.setAttributeNS($dom.XMLNS, "xmlns", $dom.SVGNS);
	svg.setAttributeNS($dom.XMLNS, "xmlns:xlink", $dom.XLINK);
	svg.setAttribute("role", "group");
	this.container.appendChild(svg);

	// 添加描述标签desc
	//let desc: SVGElement = <SVGElement>document.createElementNS($dom.SVGNS, "desc");
	//desc.appendChild(document.createTextNode("JavaScript chart by amCharts"));
	//svg.appendChild(desc);

	// 添加defs标签
	this.defs = <SVGDefsElement>document.createElementNS($dom.SVGNS, "defs");
	svg.appendChild(this.defs);

	// 给svg节点设置width,height
	svg.style.width = "100%";
	svg.style.height = "100%";
	svg.style.overflow = "visible";

	this.svg = svg;
}

//创建一个新的元素,
public add(elementName: SVGElementNames): AMElement {
	return new AMElement(elementName);
}

//创建一个新的Group元素
public addGroup(groupName: SVGElementNames): Group {
	return new Group(groupName);
}

image.png

createElementNS(namespaceURI, qualifiedName)
createElementNS(namespaceURI, qualifiedName, options)

其中,NameSpaceURL 仅限如下三个:

AMElement类,包含基本的属性、方法

export class AMElement implements IDisposer{
 ....
}

windows.getComputedStyle

image.png

/**
 * Returns element's width.
 *
 * @ignore Exclude from docs
 * @param element  Element
 * @return Width (px)
 * @deprecated Not used anywhere
 */
export function width(element: HTMLElement): number {

	let cs = getComputedStyle(element);

	let paddingX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
	let borderX = parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth);

	return element.clientWidth - paddingX - borderX;
}

style设置使用node.style

/**
	 * Adds style attributes to element's node.
	 *
	 * @param attributes  Object containing attribute: value pairs
	 * @return The same element
	 */
public addStyle(attributes: Object): AMElement {
	// @todo Review because it's a bit messy and maybe not needed (pratically not used)
	$object.each(attributes, (attributeName, attributeValue) => {
		if (!$type.hasValue(attributeValue)) {
			this.removeStyle(attributeName);
		}
		else {
			(<any>this.node.style)[attributeName] = attributeValue;
		}
	});
	return this;
}

属性设置使用node.setAttributes

/**
	 * Sets a set of attributes on a element.
	 *
	 * @param attributes  An object with attribute names (key) and values
	 * @return The same element
	 */
public attr(attributes: ISVGAttribute): AMElement {
	$object.each(attributes, (attributeName, attributeValue) => {
		if (!$type.hasValue(attributeValue)) {
			this.node.removeAttribute(attributeName);
		}
		else {
			// this is for performance testing
			//if(attributeValue == this.node.getAttribute(attributeName)){
			//	console.log(attributeName, attributeValue)
			//}
			this.node.setAttribute(attributeName, attributeValue);
		}
	});
	return this;
}

dispose方法 -- 最终就是从父类中移除子节点

/**
	 * Removes element's node from DOM.
	 */
public removeNode(): void {
	if (this.node) {
		if (this.node.parentNode) {
			this.node.parentNode.removeChild(this.node);
		}
	}
}

参考

Amchart Paper

SVGElement