我正在尝试编写图形化网格编辑器,并且正在寻找使用SVG绘制网格的可能性,希望可以选择网格元素。因此,SVG网格将由按列和行排列的彩色矩形组成。用户可以通过为不同的矩形着色不同的颜色来绘制数字图片。
我可以轻松地绘制svg rect网格,并且显示效果很好。但是我希望用户能够从svg显示中选择一组rect。因此,也许他们想通过用鼠标拖动一个矩形区域并选择它们来选择多个矩形,然后他们可能想为所有特定颜色着色。
浏览器是否可以显示在网格中显示的部分rect的选择?还是SVG不可能吗?我是SVG的新手,所以以前从未使用过它。我的简单网格测试在用鼠标拖动svg rect元素时不显示任何选择。
有一些简单的方法可以做到这一点吗?
或者,我认为我需要使用HTML 5画布来显示和自己处理所有鼠标事件。
答案 0 :(得分:0)
这就是我要做的:
我创建了网格,并将矩形存储在rects
数组中。
在鼠标按下时,我更改了min_x
和min_y
变量的值。
在鼠标悬停时,我更改max_x
和max_y
的值,并过滤rects
数组以在选定范围内更改矩形的颜色:>
x >= min_x-size &&
y >= min_y-size &&
x <= max_x &&
y <= max_y
这是一个例子。请点击并拖动到svg画布上。
let SVG_NS = svg.namespaceURI;
let size = 10;// the size of a grid cell
let w = 100;//the width of the grid
let h = 100;//the height of the grid
let rectx=0,recty=0;
let selecting = false;
// the rects array
let rects = [];
//create the grid.Push the new rect into the rects array. All the recta have a fill attribute
for(let y = 0; y< h; y+=size){
for(let x = 0; x < w; x+=size){
let rect = drawSVGelmt({x:x,y:y,width:size,height:size,fill:"white"},"rect", svgG);
rects.push(rect)
}
}
let min_x = 0,max_x=100,min_y=0,max_y = 100
//on mouse down change the value of the min_x and min_y
svg.addEventListener("mousedown",(e)=>{
selecting = true
m = oMousePosSVG(e,svg)
min_x = m.x,min_y=m.y;
rectx = m.x;
recty = m.y;
selector.setAttributeNS(null,"x",rectx);
selector.setAttributeNS(null,"y",recty);
})
//on mouse up change the value of the max_x and max_y, filter the rects array and change the color of the "selected" rects
svg.addEventListener("mousemove",(e)=>{
if(selecting){
m = oMousePosSVG(e,svg);
selector.setAttributeNS(null,"width",m.x-rectx);
selector.setAttributeNS(null,"height",m.y-recty);
}
});
svg.addEventListener("mouseup",(e)=>{
if(selecting){
let m = oMousePosSVG(e,svg)
max_x = m.x,max_y=m.y;
selector.setAttributeNS(null,"x",0);
selector.setAttributeNS(null,"y",0);
selector.setAttributeNS(null,"width",0);
selector.setAttributeNS(null,"height",0);
rects.filter((el)=> {
let x = el.getAttribute("x");
let y = el.getAttribute("y");
if (x >= min_x-size &&
y >= min_y-size &&
x <= max_x &&
y <= max_y){
el.setAttribute("fill","red")}
});
}
selecting = false;
})
// a function to draw a new svg element
function drawSVGelmt(o,tag, parent) {
let elmt = document.createElementNS(SVG_NS, tag);
for (let name in o) {
if (o.hasOwnProperty(name)) {
elmt.setAttributeNS(null, name, o[name]);
}
}
parent.appendChild(elmt);
return elmt;
}
// a function to detect the mouse position on the svg canvas
function oMousePosSVG(e, svg) {
var p = svg.createSVGPoint();
p.x = e.clientX;
p.y = e.clientY;
var ctm = svg.getScreenCTM().inverse();
var p = p.matrixTransform(ctm);
return p;
}
svg{border:1px solid; width:90vh;}
rect{stroke:black; vector-effect:non-scaling-stroke;pointer-events:all}
<svg id="svg" viewBox="0 0 100 100">
<g id="svgG"></g>
<rect id="selector" stroke="#ccc" fill="rgba(0,0,0,.2)" />
</svg>