我有两个y轴,时间作为数据。 我想在相应的轴上点击刻度时添加和删除一行。 生成线但不确定如何删除线。我尝试使用
var data = [{
"inTime": "2013-04-24T00:00:00-05:00",
"outTime": "2013-04-24T00:00:00-05:00"
}, {
"inTime": "2013-04-24T00:00:00-05:00",
"outTime": "2013-04-24T00:00:00-05:00"
}, {
"inTime": "2013-04-24T00:00:00-05:00",
"outTime": "2013-04-24T00:00:00-05:00"
}, {
"inTime": "2013-04-26T00:00:00-05:00",
"outTime": "2013-04-26T00:00:00-05:00"
},
];
var margin = {
top: 40,
right: 40,
bottom: 40,
left: 40
},
width = 600,
height = 700;
//Define Left Y axis
var y = d3.time.scale()
.domain([new Date(data[0].inTime), d3.time.day.offset(new Date(data[data.length - 1].inTime), 1)])
.rangeRound([0, width - margin.left - margin.right]);
//Define Right Y axis
var y1 = d3.time.scale()
.domain([new Date(data[1].inTime), d3.time.day.offset(new Date(data[data.length - 1].outTime), 1)])
.rangeRound([0, width - margin.left - margin.right]);
//Left Yaxis attributes
var yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.tickFormat(d3.time.format('%m/%d %H:%M'))
.tickSize(8)
.tickPadding(8);
//Right Yaxis attributes
var yAxisRight = d3.svg.axis()
.scale(y1)
.orient('right')
.tickFormat(d3.time.format('%m/%d %H:%M'))
.tickSize(8)
.tickPadding(8);
//Create chart
var svg = d3.select('body').append('svg')
.attr('class', 'chart')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
//Add left Yaxis to group
svg.append('g')
.attr('class', 'y axis')
.attr('transform', 'translate(100, 5)')
.call(yAxis);
//Add right Yaxis to group
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(400, 1)')
.call(yAxisRight);
var parse = d3.time.format('%m/%d %H:%M');
//Function to add a line between two ticks
function addLine(t1, t2) {
var ticks = {};
d3.selectAll('.tick text').each(function(d) {
ticks[d3.select(this).text()] = this;
});
var pos1 = ticks[t1].getBoundingClientRect();
var pos2 = ticks[t2].getBoundingClientRect();
svg.append('line')
.attr('x1', pos1.top - pos1.width)
.attr('y1', pos1.top + 5)
.attr('x2', pos2.left - 5)
.attr('y2', pos2.top + 5)
.style('stroke', 'black')
}
var ticks = svg.selectAll(".tick");
ticks.attr('class', function(d, i) {
return 'ticks' + i;
}).each(function(d, i) {
d3.select(this).append("circle")
.attr('id', function(d) {
return 'tickCircle' + i;
})
.attr('class', function(d) {
return 'tickCircles' + this.id
})
.attr("r", 5)
.on('click', function(d) {
console.log('clicked')
return addLineNew(this);
})
.on('mouseover', function(d){
d3.select(this).style('fill','red'); })
.on('mouseout', function(d){
d3.select(this).style('fill','black'); })
});
ticks.selectAll("line").remove();
var firstTick;
var secondTick;
var secondTickMap={};
var firstTickMap={};
var allLines=[];
//add Line
function addLineNew(element) {
if (firstTick && secondTick) {
firstTick = '';
secondTick = '';
}
if (!firstTick || firstTick === '') {
firstTick = element.id
}
else if ((secondTick != 'undefined' || secondTick === '') && !(secondTick in firstTickMap)) {
secondTick = element.id
}
if (firstTick && secondTick) {
if(firstTick == secondTick){
if(firstTick in firstTickMap){delete firstTickMap.firstTick;}
else if(firstTick in secondTickMap){delete secondTickMap.firstTick;}
if(secondTick in firstTickMap){delete firstTickMap.secondTick;}
else if(secondTick in secondTickMap ){delete secondTickMap.secondTick;}
}
if(!(firstTick in firstTickMap) && !(secondTick in secondTickMap) && !(firstTick in secondTickMap) && !(secondTick in firstTickMap))
{
var firstTickBBox = getBBox(firstTick)
var secondTickBBox = getBBox(secondTick);
var firstTickPos = getCenterPoint(firstTickBBox);
var secondTickPos = getCenterPoint(secondTickBBox);
firstTickMap[firstTick] = firstTick;
secondTickMap[secondTick] = secondTick;
createLine(firstTickPos, secondTickPos)
}
}
}
//get Center Point
function getCenterPoint(element) {
var thisX = element.left + element.width / 2;
var thisY = element.top + element.height / 2;
return [thisX, thisY]
}
function getBBox(element) {
var thisEl = document.getElementById(element).getBoundingClientRect();
return thisEl;
}
//create a line between pointA and pointB
function createLine(pointA, pointB) {
var thisData = {
x1: pointA[0],
y1: pointA[1],
x2: pointB[0],
y2: pointB[1]
};
allLines.push(svg.data([thisData]).append('line')
.attr('x1', function(d) {
console.log(d)
return d.x1;
})
.attr('y1', function(d) {
return d.y1;
})
.attr('x2', function(d) {
return d.x2;
})
.attr('y2', function(d) {
return d.y2;
}).style('stroke', 'black')
.style('stroke-width','1')
.attr('transform', 'translate(' + (-margin.left - 5) + ', ' + (- margin.top - 5) + ')'));
}

但完全删除了图表。
更详细信息 各轴的刻度之间存在1-1的关系。
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
&#13;
{{1}}&#13;
答案 0 :(得分:1)
首先让我们澄清一些事情。在创建线条时,将线条数组推送到如下所示的数组:
allLines.push(svg.data([thisData]).append('line')...
这不是正确的方法。最好的方法是,在创建一条线时,将数据线(例如x1,y1,x2,y2等)推送到数组,并使用此数组一次创建所有线。这就是D3的工作方式。
所以我改变了你的功能。
function createLine(pointA, pointB) {
var thisData = {
x1: pointA[0],
y1: pointA[1],
x2: pointB[0],
y2: pointB[1]
};
allLinesData.push(thisData) //push points into array
drawLines(allLinesData); //draw all lines at once from 'allLinesData'
}
绘制线条的功能:
function drawLines(data) { //pass the data you want
var line = svg.selectAll('.line').data(data);
line.enter().append('line')
.attr('id', function(d, i) {return 'genLine' + i; })
.attr('x1', function(d) { return d.x1;})
.attr('y1', function(d) { return d.y1; })
.attr('x2', function(d) { return d.x2; })
.attr('y2', function(d) { return d.y2; })
.style('stroke', 'black')
.style('stroke-width', '3')
.on('mouseover', function(d) { d3.select(this).style('stroke', 'red') })
.on('mouseout', function(d) { d3.select(this).style('stroke', 'black') })
.attr('transform', 'translate(' + (-margin.left - 5) + ', ' + (-margin.top - 5) + ')')
line.on('dblclick', function(d) { //delete line
var thisLine = this;
line.each(function(e, i) {
var thisLine2 = this;
if (thisLine.id === thisLine2.id) {
console.log('splice')
allLinesData.splice(i--, 1); //remove from array you use to feed the line drawer
d3.select(this).remove(); //remove it from DOM
}
})
})
line.exit().remove(); //remove unwanted lines
}
还添加了&#39; mouseover&#39;所以你知道你在哪一行。
这是一个工作小提琴:https://jsfiddle.net/reko91/vr09w905/1/
此外,如果你只想在这里:
var data = [{
"inTime": "2013-04-24T00:00:00-05:00",
"outTime": "2013-04-24T00:00:00-05:00"
}, {
"inTime": "2013-04-24T00:00:00-05:00",
"outTime": "2013-04-24T00:00:00-05:00"
}, {
"inTime": "2013-04-24T00:00:00-05:00",
"outTime": "2013-04-24T00:00:00-05:00"
}, {
"inTime": "2013-04-26T00:00:00-05:00",
"outTime": "2013-04-26T00:00:00-05:00"
}, ];
var margin = {
top: 40,
right: 40,
bottom: 40,
left: 40
},
width = 600,
height = 700;
//Define Left Y axis
var y = d3.time.scale()
.domain([new Date(data[0].inTime), d3.time.day.offset(new Date(data[data.length - 1].inTime), 1)])
.rangeRound([0, width - margin.left - margin.right]);
//Define Right Y axis
var y1 = d3.time.scale()
.domain([new Date(data[1].inTime), d3.time.day.offset(new Date(data[data.length - 1].outTime), 1)])
.rangeRound([0, width - margin.left - margin.right]);
//Left Yaxis attributes
var yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.tickFormat(d3.time.format('%m/%d %H:%M'))
.tickSize(8)
.tickPadding(8);
//Right Yaxis attributes
var yAxisRight = d3.svg.axis()
.scale(y1)
.orient('right')
.tickFormat(d3.time.format('%m/%d %H:%M'))
.tickSize(8)
.tickPadding(8);
//Create chart
var svg = d3.select('body').append('svg')
.attr('class', 'chart')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
//Add left Yaxis to group
svg.append('g')
.attr('class', 'y axis')
.attr('transform', 'translate(100, 5)')
.call(yAxis);
//Add right Yaxis to group
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(400, 1)')
.call(yAxisRight);
var parse = d3.time.format('%m/%d %H:%M');
//Function to add a line between two ticks
function addLine(t1, t2) {
var ticks = {};
d3.selectAll('.tick text').each(function(d) {
ticks[d3.select(this).text()] = this;
});
var pos1 = ticks[t1].getBoundingClientRect();
var pos2 = ticks[t2].getBoundingClientRect();
svg.append('line')
.attr('x1', pos1.top - pos1.width)
.attr('y1', pos1.top + 5)
.attr('x2', pos2.left - 5)
.attr('y2', pos2.top + 5)
.style('stroke', 'black')
}
var ticks = svg.selectAll(".tick");
ticks.attr('class', function(d, i) {
return 'ticks' + i;
}).each(function(d, i) {
d3.select(this).append("circle")
.attr('id', function(d) {
return 'tickCircle' + i;
})
.attr('class', function(d) {
return 'tickCircles' + this.id
})
.attr("r", 5)
.on('click', function(d) {
console.log('clicked')
return addLineNew(this);
})
.on('mouseover', function(d) {
d3.select(this).style('fill', 'red');
})
.on('mouseout', function(d) {
d3.select(this).style('fill', 'black');
})
});
ticks.selectAll("line").remove();
var firstTick;
var secondTick;
var secondTickMap = {};
var firstTickMap = {};
//var allLines = [];
var allLinesData = [];
//add Line
function addLineNew(element) {
if (firstTick && secondTick) {
firstTick = '';
secondTick = '';
}
if (!firstTick || firstTick === '') {
firstTick = element.id
} else if ((secondTick != 'undefined' || secondTick === '') && !(secondTick in firstTickMap)) {
secondTick = element.id
}
if (firstTick && secondTick) {
if (firstTick == secondTick) {
if (firstTick in firstTickMap) {
delete firstTickMap.firstTick;
} else if (firstTick in secondTickMap) {
delete secondTickMap.firstTick;
}
if (secondTick in firstTickMap) {
delete firstTickMap.secondTick;
} else if (secondTick in secondTickMap) {
delete secondTickMap.secondTick;
}
}
if (!(firstTick in firstTickMap) && !(secondTick in secondTickMap) && !(firstTick in secondTickMap) && !(secondTick in firstTickMap)) {
var firstTickBBox = getBBox(firstTick)
var secondTickBBox = getBBox(secondTick);
var firstTickPos = getCenterPoint(firstTickBBox);
var secondTickPos = getCenterPoint(secondTickBBox);
firstTickMap[firstTick] = firstTick;
secondTickMap[secondTick] = secondTick;
createLine(firstTickPos, secondTickPos)
}
}
}
//get Center Point
function getCenterPoint(element) {
var thisX = element.left + element.width / 2;
var thisY = element.top + element.height / 2;
return [thisX, thisY]
}
function getBBox(element) {
var thisEl = document.getElementById(element).getBoundingClientRect();
return thisEl;
}
//create a line between pointA and pointB
function createLine(pointA, pointB) {
var thisData = {
x1: pointA[0],
y1: pointA[1],
x2: pointB[0],
y2: pointB[1]
};
allLinesData.push(thisData) //push points into array
drawLines(allLinesData); //draw all lines at once from 'allLinesData'
}
function drawLines(data) { //pass the data you want
var line = svg.selectAll('.line').data(data);
line.enter().append('line')
.attr('id', function(d, i) {
return 'genLine' + i;
})
.attr('x1', function(d) {
return d.x1;
})
.attr('y1', function(d) {
return d.y1;
})
.attr('x2', function(d) {
return d.x2;
})
.attr('y2', function(d) {
return d.y2;
})
.style('stroke', 'black')
.style('stroke-width', '3')
.on('mouseover', function(d) {
d3.select(this).style('stroke', 'red')
})
.on('mouseout', function(d) {
d3.select(this).style('stroke', 'black')
})
.attr('transform', 'translate(' + (-margin.left - 5) + ', ' + (-margin.top - 5) + ')')
line.on('dblclick', function(d) { //delete line
var thisLine = this;
line.each(function(e, i) {
var thisLine2 = this;
if (thisLine.id === thisLine2.id) {
console.log('splice')
allLinesData.splice(i--, 1); //remove from array you use to feed the line drawer
d3.select(this).remove(); //remove it from DOM
}
})
})
line.exit().remove(); //remove unwanted lines
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
&#13;