Я пытаюсь нарисовать объект, используя lineGenerator с D3, до сих пор с помощью щелчка я рисовал линию и перетаскивался, но мне нужно, чтобы этот объект был изменяемого размера, потому что мне нужно с ним сгенерировать фамилограмму, и таким образом чтобы объединить различные нарисованные объекты.
Элемент управления для этого - «Путь к линии».
Я ищу информацию, чтобы сделать это, но до сих пор я ничего не нашел.
Спасибо за любую помощь.
Демо
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>FAM</title>
<script type="text/javascript" src="jquery-min.js"></script>
<script type="text/javascript" src="jquery-ui-min.js"></script>
<script type="text/javascript" src="d3.v4.min.js"></script>
<link rel="stylesheet" type="text/css" href="jquery-ui.min.css"/>
<script type="text/javascript">
$(function () {
var svg = d3.select('#svf');
var container = svg.append('g');
var object = null, line = null, path = null, i = 0, j = 0;
var pointspath = new Array();
function cuadricula(container) {
for (i = 0; i < 860; i = i + 10) {
container.append('line').attr('x1', i).attr('y1', 0).attr('x2', i).attr('y2', 860).attr('stroke', '#CFCECE').attr('stroke-width', 1).attr('fill', 'none');
}
for (j = 0; j < 460; j = j + 10) {
container.append('line').attr('x1', 1).attr('y1', j).attr('x2', 860).attr('y2', j).attr('stroke', '#CFCECE').attr('stroke-width', 1).attr('fill', 'none');
}
}
cuadricula(container);
function main() {
var coords = d3.mouse(this), x = coords[0], y = coords[1];
var lnk = $('#dv_conv').find('a[data-pressed="1"]');
var conv = lnk.attr('data-conv');
if (conv == 1) {
var grp = container.append('g').attr('class', 'gwoman');
grp.append('circle').attr('class', 'woman').attr('name', '').attr('age', '').attr('job', '').attr('cx', x).attr('cy', y).attr('r', 20).attr('stroke-width', 2).attr('stroke', '#000').attr('fill', 'transparent');
grp.on('click', clicked).call(d3.drag().on('start', dragstarted).on('drag', dragged_woman).on('end', dragended))
}
if (conv == 2) {
container.append('rect').attr('nombre', '').attr('edad', '').attr('ocupacion', '').attr('x', x).attr('y', y).attr('width', 40).attr('height', 40).attr('stroke-width', 2).attr('stroke', '#000').attr('fill', 'transparent').on('click', clicked).call(d3.drag().on('start', dragstarted).on('drag', dragged_rect).on('end', dragended));
}
if (conv == 5) {
container.append('text').attr('x', x).attr('y', y).text('Hello World').on('click', clicked).call(d3.drag().on('start', dragstarted).on('drag', dragged_text).on('end', dragended));
}
if (conv == 7) {
pointspath[pointspath.length] = [x, y];
var lineGenerator = d3.line();
var pathData = lineGenerator(pointspath);
if (!path) {
path = container.append('path').attr('d', pathData).attr('stroke', '#000').attr('stroke-width', 2).attr('fill', 'none').on('click', clicked).call(d3.drag().on('start', dragstarted).on('drag', dragged_path).on('end', dragended));
} else {
path.attr('d', pathData);
}
}
}
function mousedown() {
var lnk = $('#dv_conv').find('a[data-pressed="1"]');
var conv = lnk.attr('data-conv');
if (conv == 3) {
var m = d3.mouse(this);
line = container.append('line').attr('x1', m[0]).attr('y1', m[1]).attr('x2', m[0]).attr('y2', m[1]).attr('stroke', '#000').attr('stroke-width', 2).attr('fill', 'transparent').on('click', clicked).call(d3.drag().on("start", dragstarted).on("drag", dragged_line).on("end", dragended));
svg.on('mousemove', mousemove);
}
if (conv == 6) {
var m = d3.mouse(this);
var lineGenerator = d3.line().curve(d3.curveCardinal);
pointspath[pointspath.length] = [m[0], m[1]];
pointspath[pointspath.length] = [m[0], m[1]];
var pathData = lineGenerator(pointspath);
path = container.append('path').attr('d', pathData).attr('stroke', '#000').attr('stroke-width', 1).attr('fill', 'transparent').on('click', clicked).call(d3.drag().on("start", dragstarted).on("drag", dragged_path).on("end", dragended));
svg.on('mousemove', mousemove);
}
}
function mousemove() {
var lnk = $('#dv_conv').find('a[data-pressed="1"]');
var conv = lnk.attr('data-conv');
if (conv == 3) {
var m = d3.mouse(this);
line.attr('x2', m[0]).attr('y2', m[1]);
console.log('x=' + m[0] + 'y=' + m[1]);
}
if (conv == 6) {
var lineGenerator = d3.line().curve(d3.curveCardinal);
var m = d3.mouse(this);
pointspath[pointspath.length] = [m[0], m[1]];
var pathData = lineGenerator(pointspath);
path.attr('d', pathData);
}
}
function mouseup() {
svg.on('mousemove', null);
svg.on('click', null);
}
function dragstarted(d) {
d3.select(this).raise().classed('active', true);
}
function dragged_circle(d) {
d3.select(this).attr('cx', +d3.select(this).attr('cx') + d3.event.dx);
d3.select(this).attr('cy', +d3.select(this).attr('cy') + d3.event.dy);
}
function dragged_rect(d) {
d3.select(this).attr('x', +d3.select(this).attr('x') + d3.event.dx);
d3.select(this).attr('y', +d3.select(this).attr('y') + d3.event.dy);
}
function dragged_text(d) {
d3.select(this).attr('x', +d3.select(this).attr('x') + d3.event.dx);
d3.select(this).attr('y', +d3.select(this).attr('y') + d3.event.dy);
}
function dragged_line(d) {
this.x = this.x || 0;
this.y = this.y || 0;
this.x += d3.event.dx;
this.y += d3.event.dy;
d3.select(this).attr('transform', 'translate(' + this.x + ',' + this.y + ')');
}
function dragged_path(d) {
this.x = this.x || 0;
this.y = this.y || 0;
this.x += d3.event.dx;
this.y += d3.event.dy;
d3.select(this).attr('transform', 'translate(' + this.x + ',' + this.y + ')');
}
function dragged_woman() {
this.x = this.x || 0;
this.y = this.y || 0;
this.x += d3.event.dx;
this.y += d3.event.dy;
d3.select(this).attr('transform', 'translate(' + this.x + ',' + this.y + ')');
}
function dragended(d) {
d3.select(this).classed('active', false);
}
d3.select('body').on('keydown', function () {
if (d3.event.keyCode === 27) {
svg.on('mousemove', null);
var lnk = $('#dv_conv').find('a[data-pressed="1"]');
var conv = lnk.attr('data-conv');
if (conv == 3) {
svg.on('click', mousedown);
}
if (conv == 6 || conv == 7) {
path = null;
pointspath = new Array();
}
}
});
function clicked(d, i) {
var lnk = $('#dv_conv').find('a[data-pressed="1"]');
var conv = lnk.attr('data-conv');
if (conv == 20) {
d3.select(this).remove();
}
}
$('#lnk_circle').click(function () {
svg.on('click', main);
$('#lnk_rectangle').attr('data-pressed', 0);
$('#lnk_line').attr('data-pressed', 0);
$('#lnk_linepath').attr('data-pressed', 0);
$('#lnk_path').attr('data-pressed', 0);
$('#lnk_erase').attr('data-pressed', 0);
$(this).attr('data-pressed', 1);
return false;
});
$('#lnk_rectangle').click(function () {
svg.on('click', main);
$('#lnk_circle').attr('data-pressed', 0);
$('#lnk_line').attr('data-pressed', 0);
$('#lnk_linepath').attr('data-pressed', 0);
$('#lnk_path').attr('data-pressed', 0);
$('#lnk_erase').attr('data-pressed', 0);
$(this).attr('data-pressed', 1);
return false;
});
$('#lnk_line').click(function () {
svg.on('click', mousedown).on("dblclick", mouseup);
$('#lnk_circle').attr('data-pressed', 0);
$('#lnk_rectangle').attr('data-pressed', 0);
$('#lnk_linepath').attr('data-pressed', 0);
$('#lnk_path').attr('data-pressed', 0);
$('#lnk_erase').attr('data-pressed', 0);
$(this).attr('data-pressed', 1);
return false;
});
$('#lnk_path').click(function () {
svg.on('click', mousedown).on("dblclick", mouseup);
$('#lnk_circle').attr('data-pressed', 0);
$('#lnk_rectangle').attr('data-pressed', 0);
$('#lnk_linepath').attr('data-pressed', 0);
$('#lnk_line').attr('data-pressed', 0);
$('#lnk_erase').attr('data-pressed', 0);
$(this).attr('data-pressed', 1);
return false;
});
$('#lnk_text').click(function () {
svg.on('click', main);
$('#lnk_circle').attr('data-pressed', 0);
$('#lnk_rectangle').attr('data-pressed', 0);
$('#lnk_line').attr('data-pressed', 0);
$('#lnk_linepath').attr('data-pressed', 0);
$('#lnk_path').attr('data-pressed', 0);
$('#lnk_erase').attr('data-pressed', 0);
$(this).attr('data-pressed', 1);
return false;
});
$('#lnk_linepath').click(function () {
svg.on('click', main);
$('#lnk_line').attr('data-pressed', 0);
$('#lnk_circle').attr('data-pressed', 0);
$('#lnk_rectangle').attr('data-pressed', 0);
$('#lnk_path').attr('data-pressed', 0);
$('#lnk_erase').attr('data-pressed', 0);
$(this).attr('data-pressed', 1);
return false;
});
$('#lnk_erase').click(function () {
svg.on('click', null);
$('#lnk_circle').attr('data-pressed', 0);
$('#lnk_rectangle').attr('data-pressed', 0);
$('#lnk_line').attr('data-pressed', 0);
$('#lnk_linepath').attr('data-pressed', 0);
$(this).attr('data-pressed', 1);
return false;
});
$('#dv_member').dialog({
autoOpen: false,
resizable: false,
height: 260,
width: 450,
modal: true,
buttons: {
Guardar: function () {
save_member();
$(this).dialog('close');
},
Cancelar: function () {
$(this).dialog('close');
}
},
close: function () {
$('#txt_name,#txt_age,#txt_job').val('');
}
});
$('#svf').on('contextmenu', '.gwoman', function () {
object = $(this);
var circle = object.find('circle.woman');
var cx = +circle.attr('cx'),
cy = +circle.attr('cy'),
coords = getScreenCoords(cx, cy, circle);
console.log(coords.x, coords.y);
return false;
});
function getScreenCoords(x, y, element) {
var ctm = element.get(0).getScreenCTM();
var xn = ctm.e + x * ctm.a + y * ctm.c;
var yn = ctm.f + x * ctm.b + y * ctm.d;
return {x: xn, y: yn};
}
});
</script>
<style>
line,circle,rect,polyline{ shape-rendering:crispEdges;}
</style>
</head>
<body>
<div id="dv_fam">
<div id="dv_conv" style="float: left;width:200px;border:1px solid #000;margin-right: 1px">
<a href="#" id="lnk_circle" data-pressed="0" data-conv="1">Circle</a><br/>
<a href="#" id="lnk_rectangle" data-pressed="0" data-conv="2">Rectangle</a><br/>
<a href="#" id="lnk_line" data-pressed="0" data-conv="3">Line</a><br/>
<a href="#" id="lnk_text" data-pressed="0" data-conv="5">Text</a><br/>
<a href="#" id="lnk_path" data-pressed="0" data-conv="6">Path</a><br/>
<a href="#" id="lnk_linepath" data-pressed="0" data-conv="7">Line Path</a><br/>
<a href="#" id="lnk_erase" data-pressed="0" data-conv="20">Erase</a><br/>
</div>
<div id="dv_familiogram" style="float: left;width:500px;height: 500px;border:1px solid #000;overflow: hidden">
<svg id="svf" style="width:500px;height:500px"></svg>
</div>
<div id="dv_member" title="">
<div>
<label>Name</label>
<input type="text" id="txt_name" maxlength="100"/>
</div>
<div>
<label>Job</label>
<input type="text" id="txt_job" maxlength="100"/>
</div>
<div>
<label>Age</label>
<input type="text" id="txt_age" maxlength="3"/>
</div>
</div>
</div>
</body>
</html>