我正在尝试创建控件,允许我使用(nw,n,ne,e,se,s,sw,w)控件调整当前对象(在本例中为图像)的大小,当没有旋转调整大小时工作完善否则它不起作用,我试图解决它,我也搜索它,但我最后在这里寻求帮助。
顺便说一句,我不想使用svgjs等插件
这是我的代码: https://jsfiddle.net/z0fd9fqe/13/
HTML:
<svg width="400" height="400" transform="scale(1)">
<rect id="_svg_editor_background_" fill="#fafafa" width="100%" height="100%"></rect>
<g id="active_group" transform="">
<rect x="100" y="138" width="200" height="125" stroke-width="2" stroke="red" fill="transparent" class="active-control-border" pointer-events="none"></rect>
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://eskipaper.com/images/berries-nature-winter-1.jpg" preserveAspectRatio="none" x="100" y="138.5" width="200px" class=""></image>
<circle cx="200" cy="200.5" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-center" style="null"></circle>
<circle cx="200" cy="118" r="6" fill="rgba(150, 243, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-rotator" style="cursor: crosshair;"></circle>
<circle cx="100" cy="138" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-nw" style="cursor: nw-resize;"></circle>
<circle cx="200" cy="138" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-n" style="cursor: n-resize;"></circle>
<circle cx="300" cy="138" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-ne" style="cursor: ne-resize;"></circle>
<circle cx="300" cy="200.5" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-e" style="cursor: e-resize;"></circle>
<circle cx="300" cy="263" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-se" style="cursor: se-resize;"></circle>
<circle cx="200" cy="263" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-s" style="cursor: s-resize;"></circle>
<circle cx="100" cy="263" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-sw" style="cursor: sw-resize;"></circle>
<circle cx="100" cy="200.5" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-w" style="cursor: w-resize;"></circle>
</g>
</svg>
<div id="console">
X: <span id="x">0px</span><br>
Y: <span id="y">0px</span><br>
Width: <span id="width">0px</span><br>
Height: <span id="height">0px</span><br>
Center: <span id="center">0px</span><br>
Rotation: <span id="rot">0deg</span><br>
Rotation Center: <span id="rotcenter">{x:0px,y:0px}</span><br>
</div>
CSS:
#console{
position:absolute;
bottom:10px;
left:10px;
}
JS:
//DRAGGING
$('image').mousedown(function(e){
if (!$(this).is('[class^=active-control-]') && !$(e.target).is('[class^=active-control-]')) {
var elem = this;
if ($(this).is('g#active_group')) {
elem = $(this).find(':not([class^=active-control-])').get(0);
}
var pageX0 = e.pageX;
var pageY0 = e.pageY;
var init_scale = {width: elem.getBBox().width, height: elem.getBBox().height};
var init_offset = {x: parseInt($(elem).attr('x')), y: parseInt($(elem).attr('y'))};
function handle_dragging(e) {
var x = init_offset.x + (e.pageX - pageX0);
var y = init_offset.y + (e.pageY - pageY0);
//change center of rotation to match new element center when dragging
var trans = transform2Array(elem);
if (!Object.values(trans).length) {
trans = transform2Array($(elem).parent());
}
var transform = "";
if (trans.rotate != undefined) {
var rot_cx = x + init_scale.width / 2;
var rot_cy = y + init_scale.height / 2;
transform += "rotate(" + trans.rotate[0] + "," + rot_cx + "," + rot_cy + ")";
}
$(elem).attr({x: x, y: y});
//fix bug rotate +90 drag rotate clear select& drag => rotate svg element !
if ($(elem).parent().is('g#active_group'))
$(elem).parent().attr({transform: transform});
updateControls($(elem));//update controls to match the new position
}
function handle_mouseup(e) {
$('body')
.off('mousemove', handle_dragging)
.off('mouseup', handle_mouseup);
}
$('body')
.on('mouseup', handle_mouseup)
.on('mousemove', handle_dragging);
}
});
//END OF DRAGGING
$('circle[class^=active-control-]').mousedown(function(md_e) {
var $control = $(this);
var $element = $('image:first');
var control_name = $(this).attr('class').replace('active-control-', '').trim();
var pageX0 = md_e.pageX;
var pageY0 = md_e.pageY;
var init_offset = {
x: $element.get(0).getBBox().x,
y: $element.get(0).getBBox().y
};
var init_scale = {
width: $element.get(0).getBBox().width,
height: $element.get(0).getBBox().height
};
console.log('im dragging from ' + control_name);
function handle_dragging(d_e) {
if (control_name == 'rotator') {
//rotate fix source: https://stackoverflow.com/questions/32640642/svg-angle-rotation-by-mousemove-touchmove-bug
var rx = parseFloat($element.get(0).getBBox().width);
var ry = parseFloat($element.get(0).getBBox().height);
var ctm = $element.get(0).getScreenCTM()
var p = $('svg').get(0).createSVGPoint()
p.x = d_e.clientX
p.y = d_e.clientY
p = p.matrixTransform(ctm.inverse())
var elem_center_x = init_offset.x + rx / 2;
var elem_center_y = init_offset.y + ry / 2;
var radians = Math.atan2(elem_center_x - p.x, elem_center_y - p.y);
var degree = (radians * (180 / Math.PI) * -1) + 0;
var new_angle = (getAngle($element) + degree);
if (new_angle > 360) {
new_angle -= 360;
}
if (new_angle < -360) {
new_angle += 360;
}
$('#console #rot').text(new_angle+"deg");
$('#console #rotcenter').text(JSON.stringify({x:elem_center_x+"px",y:elem_center_y+"px"}));
if ($element.parent().is('g#active_group') || $element.is('g#active_group')) {
$element.parent()
.attr("transform", "rotate(" + new_angle + "," + elem_center_x + "," + elem_center_y + ")");
}
} else {
makeResize(control_name[0]);
if (control_name.length == 2) {
makeResize(control_name[1]);
}
}
updateControls($element);
function makeResize(direction) {
var dx = d_e.pageX - pageX0;
var dy = d_e.pageY - pageY0;
//do resizing here for each control while image is rotated at any angle
//change width, height, and coords(x,y)
switch (direction) {
case "e":
$element.attr('width', Math.max(init_scale.width + dx, 10));
break;
case "w":
if ($element.attr('width') != 10)
$element.attr('x', init_offset.x + dx);
$element.attr('width', Math.max(init_scale.width - dx, 10));
break;
case "s":
$element.attr('height', Math.max(init_scale.height + dy, 10));
break;
case "n": //
if ($element.attr('height') != 10)
$element.attr('y', init_offset.y + dy);
$element.attr('height', Math.max(init_scale.height - dy, 10));
break;
}
}
}
function handle_mouseup() {
$('body').css('cursor', 'default');
$('body')
.off('mousemove', handle_dragging)
.off('mouseup', handle_mouseup);
}
$('body')
.on('mouseup', handle_mouseup)
.on('mousemove', handle_dragging);
});
function updateControls($element) {
$element = $($element); //ensure its jquery object
var width = parseInt($element.get(0).getBBox().width),
height = parseInt($element.get(0).getBBox().height),
data = {
x: parseInt($element.attr('x')),
y: parseInt($element.attr('y')),
rx: width,
ry: height,
angle: 0
};
var controls = [{
x: data.x + data.rx / 2,
y: data.y - 20,
name: "rotator"
}, {
x: data.x + data.rx / 2,
y: data.y + data.ry / 2,
name: "center"
},
{
x: data.x,
y: data.y,
name: "nw"
}, {
x: data.x + data.rx / 2,
y: data.y,
name: "n"
}, {
x: data.x + data.rx,
y: data.y,
name: "ne"
}, {
x: data.x + data.rx,
y: data.y + data.ry / 2,
name: "e"
},
{
x: data.x + data.rx,
y: data.y + data.ry,
name: "se"
}, {
x: data.x + data.rx / 2,
y: data.y + data.ry,
name: "s"
}, {
x: data.x,
y: data.y + data.ry,
name: "sw"
}, {
x: data.x,
y: data.y + data.ry / 2,
name: "w"
}
];
var bounderAttrs = {
x: $element.attr('x'),
y: $element.attr('y'),
width: $element.attr('width'),
height: $element.attr('height'),
};
$('#console #x').text($element.attr('x')+"px");
$('#console #y').text($element.attr('y')+"px");
$('#console #width').text(bounderAttrs.width);
$('#console #height').text(bounderAttrs.height?bounderAttrs.height+"px":'AUTO SCALED');
if ($element.parent().is('g#active_group')) {
$element.parent().find('.active-control-border').attr(bounderAttrs);
$.each(controls, function(i, o) {
if(o.name=='center'){
$('#console #center').text(JSON.stringify({x:o.x+"px",y:o.y+"px"}));
}
$element.parent().find('circle.active-control-' + o.name).attr({
cx: o.x,
cy: o.y
});
});
return;
}
}
//get elem angle from transform attribute
function getAngle(elem) {
var angle = 0;
var trans = transform2Array(elem);
if (!Object.values(trans).length) {
trans = transform2Array(elem.parent());
}
if (trans.rotate != undefined) {
angle = parseFloat(trans.rotate[0]);
}
return angle;
}
/**
* get tranform attribute values as array transform="rotate(x,y,z) scale(x,y)"
* return {
* rotate:[x,y,z]
* scale:[x,y]
* }
*/
function transform2Array(elem) {
var transform = $(elem).attr('transform');
var transforms = {};
if (typeof transform !== 'undefined') {
$.each(transform.split(' '), function(i, o) {
if (o.length) {
var trans = o.replace(')', '').split('(');
transforms[trans[0]] = [];
var params = trans[1].split(',');
$.each(params, function(i, o_param) {
transforms[trans[0]].push(parseFloat(o_param));
});
}
});
}
return transforms;
}
updateControls($('image'))