-
Notifications
You must be signed in to change notification settings - Fork 0
Snap之Element
[TOC]
- tstr (string) transform string in Snap or SVG format
Gets or sets transformation of the element
返回:
{
string (string) transform string
globalMatrix (Matrix) matrix of all transformations applied to element or its parents
localMatrix (Matrix) matrix of transformations applied only to the element
diffMatrix (Matrix) matrix of difference between global and local transformation
global (string) global transformation as string
local (string) local transformation as string
toString (function) returns `string` property
}
elproto.transform = function (tstr) {
var _ = this._;
if (tstr == null) {
var papa = this,
global = new Snap.Matrix(this.node.getCTM()),
local = extractTransform(this),
ms = [local],
m = new Snap.Matrix,
i,
localString = local.toTransformString(),
string = Str(local) == Str(this.matrix) ?
Str(_.transform) : localString;
while (papa.type != "svg" && (papa = papa.parent())) {
ms.push(extractTransform(papa));
}
i = ms.length;
while (i--) {
m.add(ms[i]);
}
return {
string: string,
globalMatrix: global,
totalMatrix: m,
localMatrix: local,
diffMatrix: global.clone().add(local.invert()),
global: global.toTransformString(),
total: m.toTransformString(),
local: localString,
toString: propString
};
}
if (tstr instanceof Snap.Matrix) {
this.matrix = tstr;
this._.transform = tstr.toTransformString();
} else {
extractTransform(this, tstr);
}
if (this.node) {
if (this.type == "linearGradient" || this.type == "radialGradient") {
$(this.node, {gradientTransform: this.matrix});
} else if (this.type == "pattern") {
$(this.node, {patternTransform: this.matrix});
} else {
$(this.node, {transform: this.matrix});
}
}
return this;
};SVGGraphicsElement.getCTM()返回一个
DOMMatrix r,该矩阵表示将当前元素的坐标系统转换为其SVG视图的坐标系统的矩阵。
示例:
let s = Snap('#svg')
let rect = s.rect(10, 10, 200, 50);
let result = rect.transform("translate(50,50)");
let matrix = {
a: 1, b: 0, c: 0, d: 1, e: 10, f: 10
};
let transform = rect.transform();
console.info(transform)
rect.transform("rotate(60)")Returns the element's parent
elproto.parent = function () {
return wrap(this.node.parentNode);
};let s = Snap('#svg')
let circle = s.circle(10, 20, 30)
s.append(circle)
let parent = circle.parent()
console.info(s === parent)
console.info(parent.node === s.node)- el (Element|Set) element to append
Appends the given element to current one
elproto.append = elproto.add = function (el) {
if (el) {
if (el.type == "set") {
var it = this;
el.forEach(function (el) {
it.add(el);
});
return this;
}
el = wrap(el);
this.node.appendChild(el.node);
el.paper = this.paper;
}
return this;
};- el (Element) parent element to append to
Appends the current element to the given one
elproto.appendTo = function (el) {
if (el) {
el = wrap(el);
el.append(this);
}
return this;
};- el (Element) element to prepend
Prepends the given element to the current one
elproto.prepend = function (el) {
if (el) {
if (el.type == "set") {
var it = this,
first;
el.forEach(function (el) {
if (first) {
first.after(el);
} else {
it.prepend(el);
}
first = el;
});
return this;
}
el = wrap(el);
var parent = el.parent();
this.node.insertBefore(el.node, this.node.firstChild);
this.add && this.add();
el.paper = this.paper;
this.parent() && this.parent().add();
parent && parent.add();
}
return this;
};- el (Element) parent element to prepend to
Prepends the current element to the given one
elproto.prependTo = function (el) {
el = wrap(el);
el.prepend(this);
return this;
};- el (Element) element to insert
Inserts given element before the current one
elproto.before = function (el) {
if (el.type == "set") {
var it = this;
el.forEach(function (el) {
var parent = el.parent();
it.node.parentNode.insertBefore(el.node, it.node);
parent && parent.add();
});
this.parent().add();
return this;
}
el = wrap(el);
var parent = el.parent();
this.node.parentNode.insertBefore(el.node, this.node);
this.parent() && this.parent().add();
parent && parent.add();
el.paper = this.paper;
return this;
};- el (Element) element to insert
Inserts given element after the current one
elproto.after = function (el) {
el = wrap(el);
var parent = el.parent();
if (this.node.nextSibling) {
this.node.parentNode.insertBefore(el.node, this.node.nextSibling);
} else {
this.node.parentNode.appendChild(el.node);
}
this.parent() && this.parent().add();
parent && parent.add();
el.paper = this.paper;
return this;
};- el (Element) element next to whom insert to
Inserts the element after the given one
elproto.insertBefore = function (el) {
el = wrap(el);
var parent = this.parent();
el.node.parentNode.insertBefore(this.node, el.node);
this.paper = el.paper;
parent && parent.add();
el.parent() && el.parent().add();
return this;
};- el (Element) element next to whom insert to
Inserts the element after the given one
elproto.insertAfter = function (el) {
el = wrap(el);
var parent = this.parent();
el.node.parentNode.insertBefore(this.node, el.node.nextSibling);
this.paper = el.paper;
parent && parent.add();
el.parent() && el.parent().add();
return this;
};Removes element from the DOM
elproto.remove = function () {
var parent = this.parent();
this.node.parentNode && this.node.parentNode.removeChild(this.node);
delete this.paper;
this.removed = true;
parent && parent.add();
return this;
};- query (string) CSS selector
elproto.select = function (query) {
return wrap(this.node.querySelector(query));
};- query (string) CSS selector
返回:
- (Set|array) result of query selection
elproto.selectAll = function (query) {
var nodelist = this.node.querySelectorAll(query),
set = (Snap.set || Array)();
for (var i = 0; i < nodelist.length; i++) {
set.push(wrap(nodelist[i]));
}
return set;
};- attr (string) attribute name
- value (string) #optional attribute value
Returns given attribute of the element as a
pxvalue (not %, em, etc.)
elproto.asPX = function (attr, value) {
if (value == null) {
value = this.attr(attr);
}
return +unit2px(this, attr, value);
};示例:
let s = Snap('#svg')
s.attr({width: 200})
let rect = s.rect(0, 0, "100%", 10)
let widthAsPx = rect.asPX("width")
console.info(widthAsPx === 200)Creates a
<use>element linked to the current element
elproto.use = function () {
var use,
id = this.node.id;
if (!id) {
id = this.id;
$(this.node, {
id: id
});
}
if (this.type == "linearGradient" || this.type == "radialGradient" ||
this.type == "pattern") {
use = make(this.type, this.node.parentNode);
} else {
use = make("use", this.node.parentNode);
}
$(use.node, {
"xlink:href": "#" + id
});
use.original = this;
return use;
};Creates a clone of the element and inserts it after the element
elproto.clone = function () {
var clone = wrap(this.node.cloneNode(true));
if ($(clone.node, "id")) {
$(clone.node, {id: clone.id});
}
fixids(clone);
clone.insertAfter(this);
return clone;
};示例:
let s = Snap('#svg')
let circle = s.circle(10, 20, 30);
s.append(circle);
let clone = circle.clone();Moves element to the shared
<defs>area
function getSomeDefs(el) {
var p = el.node.ownerSVGElement && wrap(el.node.ownerSVGElement) ||
el.node.parentNode && wrap(el.node.parentNode) ||
Snap.select("svg") ||
Snap(0, 0),
pdefs = p.select("defs"),
defs = pdefs == null ? false : pdefs.node;
// 看文档中是否有defs,如果没有则创建新的defs
if (!defs) {
defs = make("defs", p.node).node;
}
return defs;
}
elproto.toDefs = function () {
var defs = getSomeDefs(this);
defs.appendChild(this.node);
return this;
};示例:
let s = Snap('#svg')
let circle = s.circle(10, 20, 30);
let result = circle.toDefs();
console.info(circle.node.parentElement.nodeName === 'defs')- x (string|number)
- y (string|number)
- width (string|number)
- height (string|number)
Creates a
<pattern>element from the current element
elproto.pattern = elproto.toPattern = function (x, y, width, height) {
var p = make("pattern", getSomeDefs(this));
if (x == null) {
x = this.getBBox();
}
if (is(x, "object") && "x" in x) {
y = x.y;
width = x.width;
height = x.height;
x = x.x;
}
$(p.node, {
x: x,
y: y,
width: width,
height: height,
patternUnits: "userSpaceOnUse",
id: p.id,
viewBox: [x, y, width, height].join(" ")
});
p.node.appendChild(this.node);
return p;
};You can use pattern later on as an argument for
fillattribute:
示例:
let s = Snap('#svg')
let p = s.paper.path("M10-5-10,15M15,0,0,15M0-5-20,15").attr({
fill: "none",
stroke: "#bada55",
strokeWidth: 5
}).pattern(0, 0, 10, 10),
c = s.paper.circle(200, 200, 100);
c.attr({
fill: p
});- x (number)
- y (number)
- width (number)
- height (number)
- refX (number) 参考点的x位置。也就是内部的坐标。以后会作为路径的起止点
- refY (number)
Creates a
<marker>element from the current element
You can specify the marker later as an argument for
marker-start,marker-end,marker-mid, andmarkerattributes. Themarkerattribute places the marker at every point along the path, andmarker-midplaces them at every point except the start and end.
elproto.marker = function (x, y, width, height, refX, refY) {
var p = make("marker", getSomeDefs(this));
if (x == null) {
x = this.getBBox();
}
if (is(x, "object") && "x" in x) {
y = x.y;
width = x.width;
height = x.height;
refX = x.refX || x.cx;
refY = x.refY || x.cy;
x = x.x;
}
$(p.node, {
viewBox: [x, y, width, height].join(" "),
markerWidth: width,
markerHeight: height,
orient: "auto",
refX: refX || 0,
refY: refY || 0,
id: p.id
});
p.node.appendChild(this.node);
return p;
};示例:
let svg = Snap("#svg");
// 圈圈
let c1 = svg.paper.circle(5, 5, 3);
// 三角
let p1 = svg.paper.path("M2,2 L2,11 L10,6 L2,2").attr({
fill: "#000"
});
// 变身标记
let m1 = c1.marker(0, 0, 8, 8, 5, 5), m2 = p1.marker(0, 0, 13, 13, 2, 6);
// 添加一个路径
let p2 = svg.paper.path("M10,10 L150,10 L150,90").attr({
// 描边
stroke: "#00f",
strokeWidth: 1,
fill: "none",
// 起始标记
markerStart: m1,
// 结束标记
"marker-end": m2
});- key (string) key to store data
- value (any) #optional value to store
elproto.data = function (key, value) {
var data = eldata[this.id] = eldata[this.id] || {};
if (arguments.length == 0){
eve("snap.data.get." + this.id, this, data, null);
return data;
}
if (arguments.length == 1) {
if (Snap.is(key, "object")) {
for (var i in key) if (key[has](i)) {
this.data(i, key[i]);
}
return this;
}
eve("snap.data.get." + this.id, this, data[key], key);
return data[key];
}
data[key] = value;
eve("snap.data.set." + this.id, this, value, key);
return this;
};示例:
let svg = Snap("#svg");
for (let i = 0; i < 5; i++) {
svg.paper.circle(10 + 15 * i, 10, 10)
.attr({fill: "#000"})
.data("i", i)
.click(function () {
alert(this.data("i"));
});
}elproto.removeData = function (key) {
if (key == null) {
eldata[this.id] = {};
} else {
eldata[this.id] && delete eldata[this.id][key];
}
return this;
};Returns SVG code for the element's contents, equivalent to HTML's
innerHTML
elproto.innerSVG = toString();
function toString(type) {
return function () {
var res = type ? "<" + this.type : "",
attr = this.node.attributes,
chld = this.node.childNodes;
if (type) {
for (var i = 0, ii = attr.length; i < ii; i++) {
res += " " + attr[i].name + '="' +
attr[i].value.replace(/"/g, '\\"') + '"';
}
}
if (chld.length) {
type && (res += ">");
for (i = 0, ii = chld.length; i < ii; i++) {
if (chld[i].nodeType == 3) {
res += chld[i].nodeValue;
} else if (chld[i].nodeType == 1) {
res += wrap(chld[i]).toString();
}
}
type && (res += "</" + this.type + ">");
} else {
type && (res += "/>");
}
return res;
};
}elproto.toDataURL = function () {
if (window && window.btoa) {
var bb = this.getBBox(),
svg = Snap.format('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{width}" height="{height}" viewBox="{x} {y} {width} {height}">{contents}</svg>', {
x: +bb.x.toFixed(3),
y: +bb.y.toFixed(3),
width: +bb.width.toFixed(3),
height: +bb.height.toFixed(3),
contents: this.outerSVG()
});
return "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svg)));
}
};