This is the 8th day of my participation in the August Text Challenge.More challenges in August
Text, insert, remove, classed
text
Text is used to draw text
- Usage:
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<div id="main">
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
<p class="item"></p>
</div>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
//style
let main= d3.select('#main')
.style('width'.'500px')
.style('height'.'500px');
main.selectAll('.item')
.style('height'.'30px')
.style('width'.'100%')
.style('background'.(d, i) = > {
console.log(d,'d>>>>>>......... ')
return i % 2 ? 'red' : 'blue'
})
.text('p')
</script>
Copy the code
Rendering effect:
Statement:Redraw the text in SVG using SVG textDraw this with d3js:
d3.select('svg')
.append('text')
.attr('x'.10)
.attr('y'.20)
.style('cursor'.'default')
.text('svg-text')
Copy the code
insert
Append is append like an element, insert is append like an element before append like append
- Usage Examples:
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<div id="main">
</div>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
// append
const svg = d3.select('#main')
.insert('svg')
.attr('width'.500)
.attr('height'.500);
//append a rect to add some attributes
svg.insert('rect')
.attr('width'.100)
.attr('height'.100)
.attr('fill'.'red')
.attr('x'.10)
.attr('y'.10)
.attr('stroke'.'blue')
</script>
Copy the code
Rendering effect:
classed
Adding one more class to a classed class means that an element is bound to more than one class
- Usage Examples:
d3.select('svg')
.class('svg')
.classed('svg-container')
Copy the code
Let’s go to today’s theme
D3js data binding
The data report
- 1. Data is a situation where an array is bound
data(data)
This sample is the index of the bound data by default, and can also be this sampledata(data, (d,idx) => d)
Specify to bind a field,This binding is important and will be discussed later - 2. Draw multiple RECTs and share binding data with them. You can see the last one
console.log()
The corresponding binding 1, 2, 3, 4, 5, 6, 7 is printed
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('body')
.append('svg')
.attr('width'.500)
.attr('height'.500);
const data = [1.2.3.4.5.6.7];
data.forEach((item= > {
svg.append('rect')
.attr('width'.20)
.attr('height'.20)
.attr('x'.20 * item)
.attr('y'.20 * item)
.attr('fill'.'red')
}))
svg.selectAll('rect')
.data(data)
.attr('stroke'.(d,idx) = > {
console.log(d,'d')})</script>
Copy the code
Effect presentation:
datum
Datum does the same thing as data, it binds data, it binds individual data
- Usage examples
svg.select('rect')
.datum(1)
.attr('stroke'.(d,idx) = > {
console.log(d,'d')})Copy the code
Data, datum Obtain data
The above mentioned binding data, that binding data can be obtained; The last line of console.log() outputs :[1,2,3,4,5,6,7]
- Usage Examples:
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('body')
.append('svg')
.attr('width'.500)
.attr('height'.500);
const data = [1.2.3.4.5.6.7];
data.forEach((item= > {
svg.append('rect')
.attr('width'.20)
.attr('height'.20)
.attr('x'.20 * item)
.attr('y'.20 * item)
.attr('fill'.'red')
}))
svg.selectAll('rect')
.data(data)
.attr('stroke'.(d,idx) = > {
console.log(d,'d')})console.log(svg.selectAll('rect').data(),'data')
</script>
Copy the code
enter
You should remember that I created the rect with forEach, which was a bit of a drag. D3 also has its own way of creating multiple elements with data. For example, the following code is to select multiple RECt bindings and call Enter, and then append is insufficient to add data using append method
Enter Example
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('body')
.append('svg')
.attr('width'.500)
.attr('height'.500);
const data = [1.2.3.4.5.6.7];
svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('width'.20)
.attr('height'.20)
//d stands for bound data,idx stands for index, and each method in D3 can use the callback function
.attr('x'.(d,idx) = > 20 * d)
.attr('y'.(d,idx) = > 20 * d)
.attr('fill'.'red')
.attr('stroke'.'blue')
.attr('strokeWidth'.1)
</script>
Copy the code
Rendering effect:
exit
Exit is not automatically filled when there is less data and more selections. It can be used with remove to remove redundant elements
Usage Examples:
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('body')
.append('svg')
.attr('width'.500)
.attr('height'.500);
const data = [1.2.3.4.5.6.7];
[1.2.3.4.5.6.7.8.9.10].forEach((item= > {
svg.append('rect')
.attr('width'.20)
.attr('height'.20)
.attr('x'.20 * item)
.attr('y'.20 * item)
.attr('fill'.'red')
}))
svg.selectAll('rect')
.data(data)
.exit()
.remove()
console.log(svg.selectAll('rect').data(),'data')
</script>
Copy the code
How do you implement a data-driven approach?
In fact, the data binding can be divided into three layers;
1. Rendering layer; 2. Modify layer; 3. Delete the layer;
- 1. Rendering layer:
enter()
(Data binding will determine whether the next call will enter the Enter layer based on the value you bind.) - 2. Modification layer:
data()
(Data binding will determine if you have modified the data based on the data binding) - 3, Delete layer:
exit()
(Data binding will detect which data you delete based on the data you bind)
The code analyzes the level of data binding
We have all three levels, so you can think of it that way for the moment
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('body')
.append('svg')
.attr('width'.500)
.attr('height'.500);
const data = [{id: 1.fill: 'red'.x: 20.y: 20}, {id: 2.fill: 'blue'.x: 40.y: 40}, {id: 3.fill: 'yellow'.x: 60.y: 60}, {id: 4.fill: 'black'.x: 80.y: 80}];
/ / modified layer
const update = svg.selectAll('rect')
.data(data)
/ / rendering layer
const enter = update.enter();
/ / delete the layer
const exit = update.exit();
enter.append('rect')
.attr('width'.20)
.attr('height'.20)
.attr('x'.(d,idx) = > d.x)
.attr('y'.(d,idx) = > d.y)
.attr('fill'.(d) = > d.fill)
.attr('stroke'.'blue')
.attr('strokeWidth'.1)
exit.remove()
</script>
Copy the code
Rendering effect:
Encapsulate as a data-driven function
Put those layers in a function to be data-driven. And you can kind of think about the three levels,
- The first time a function is called to draw: it must enter the draw layer, and all other layers are empty
- The second call to draw means that the data has changed (for example, the color has changed to fill) and that changes the data into the modification layer
- Call the function again and draw (delete one data, add one day data) this is based on what you bind
.data(data d => d.id)
The default for detection is index
Code examples:
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<div>
<button onclick="remove()">Delete a piece of data</button>
<button onclick="add()">Add a piece of data</button>
<button onclick="exit()">Modifying a data item</button>
<button onclick="all()">Add a data item, modify a data item, and delete a data item</button>
</div>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('body')
.append('svg')
.attr('width'.500)
.attr('height'.500);
let data = [{id: 1.fill: 'red'.x: 20.y: 20}, {id: 2.fill: 'blue'.x: 40.y: 40}, {id: 3.fill: 'yellow'.x: 60.y: 60}, {id: 4.fill: 'black'.x: 80.y: 80}];
draw()
function draw() {
/ / modified layer
const update = svg.selectAll('rect')
.data(data)
update.attr('x'.(d,idx) = > d.x)
.attr('y'.(d,idx) = > d.y)
.attr('fill'.(d) = > d.fill)
/ / rendering layer
const enter = update.enter();
/ / delete the layer
const exit = update.exit();
enter.append('rect')
.attr('width'.20)
.attr('height'.20)
.attr('x'.(d,idx) = > d.x)
.attr('y'.(d,idx) = > d.y)
.attr('fill'.(d) = > d.fill)
.attr('stroke'.'blue')
.attr('strokeWidth'.1)
exit.remove()
}
function remove() {
data.pop();
draw();
}
function add() {
data.push({id: Math.random() * 200.fill: 'violet'.x: 120.y: 120});
draw();
}
function exit() {
data[0].fill = 'orange';
draw();
}
function all() {
data.shift();
data.push({id: Math.random() * 200.fill: 'green'.x: 150.y: 150});
data[0].fill = 'pink';
console.log(data,'data')
draw();
}
</script>
Copy the code
Effect rendering: you may find that clicking the last button does not reflect any data(the problem is data binding. Data (data)). Instead, make it recognize id.data(data, d => d.id).
Correct data-driven functions
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<div>
<button onclick="remove()">Delete a piece of data</button>
<button onclick="add()">Add a piece of data</button>
<button onclick="exit()">Modifying a data item</button>
<button onclick="all()">Add a data item, modify a data item, and delete a data item</button>
</div>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('body')
.append('svg')
.attr('width'.500)
.attr('height'.500);
let data = [{id: 1.fill: 'red'.x: 20.y: 20}, {id: 2.fill: 'blue'.x: 40.y: 40}, {id: 3.fill: 'yellow'.x: 60.y: 60}, {id: 4.fill: 'black'.x: 80.y: 80}];
draw()
function draw() {
/ / modified layer
const update = svg.selectAll('rect')
.data(data, d= > d.id)
update.attr('x'.(d,idx) = > d.x)
.attr('y'.(d,idx) = > d.y)
.attr('fill'.(d) = > d.fill)
/ / rendering layer
const enter = update.enter();
/ / delete the layer
const exit = update.exit();
enter.append('rect')
.attr('width'.20)
.attr('height'.20)
.attr('x'.(d,idx) = > d.x)
.attr('y'.(d,idx) = > d.y)
.attr('fill'.(d) = > d.fill)
.attr('stroke'.'blue')
.attr('strokeWidth'.1)
exit.remove()
}
function remove() {
data.pop();
draw();
}
function add() {
data.push({id: Math.random() * 200.fill: 'violet'.x: Math.random() * 200.y: Math.random() * 200});
draw();
}
function exit() {
data[0].fill = 'orange';
draw();
}
function all() {
data.shift();
data.push({id: Math.random() * 200.fill: 'green'.x: 150.y: 150});
data[0].fill = 'pink';
console.log(data,'data')
draw();
}
</script>
Copy the code
conclusion
In fact, you can compare canvas. If you want to change, delete, add or modify an element in canvas, you always have to redraw it. Data binding of D3 + SVG helps us solve the advantage of no need to erase the redraw. After writing the drawing function, it would be good to call the drawing function if the data is changed. It would be even better to have a watch that listens to the data. You can refer to my own watch that I implemented before
conclusion
- Hi, I am Mihara and thank you for watching and I will work harder.
- Each method is typed out and verified, and can be copied if necessary.
- If you give help a thumbs-up 👍 is even better thank you ~~~~~
- We look forward to your attention