Skip to content

Commit 946d5cd

Browse files
committed
feat: allow text/background customization
1 parent 804bfb5 commit 946d5cd

5 files changed

Lines changed: 43 additions & 30 deletions

File tree

package-lock.json

Lines changed: 2 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
},
3636
"license": "MIT",
3737
"peerDependencies": {
38-
"d3": "^7.8.2"
38+
"d3": "^7.8.2",
39+
"lodash": "^4.17.21"
3940
},
4041
"devDependencies": {
4142
"eslint": "^8.35.0",

src/main.js

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,30 @@ import { assignPalettes } from './palettes';
77

88
const DEFAULT_OPTIONS = {
99
rowHeight: 24,
10-
rowAlternatingBackground: '#eee',
1110
padding: 5,
1211
geomPadding: 1.5,
13-
geomStroke: '#555',
1412
columnRotate: 30,
1513
midpoint: 0.8,
1614
legendFontSize: 12,
1715
legendTicks: [0, 0.2, 0.4, 0.6, 0.8, 1],
1816
labelGroupsAbc: false,
19-
colorByRank: false
17+
colorByRank: false,
18+
theme: {
19+
oddRowBackground: 'white',
20+
evenRowBackground: '#eee',
21+
textColor: 'black',
22+
strokeColor: '#555',
23+
headerColor: 'white',
24+
hoverColor: '#1385cb'
25+
}
2026
};
2127

2228
const GEOMS = {
2329
text: (value, _, __, O) => {
2430
const el = d3.create('svg:text')
2531
.attr('dominant-baseline', 'middle')
2632
.attr('y', O.rowHeight / 2)
33+
.style('fill', O.theme.textColor)
2734
.text(value);
2835
if (O.fontSize) {
2936
el.attr('font-size', O.fontSize);
@@ -40,7 +47,7 @@ const GEOMS = {
4047
.attr('y', O.geomPadding)
4148
.attr('width', width)
4249
.attr('height', O.geomSize)
43-
.style('stroke', O.geomStroke)
50+
.style('stroke', O.theme.strokeColor)
4451
.style('stroke-width', 1)
4552
.style('fill', fill);
4653
},
@@ -49,7 +56,7 @@ const GEOMS = {
4956
const fill = column.palette(colorValue);
5057
value = column.scale(value);
5158
return d3.create('svg:circle')
52-
.style('stroke', O.geomStroke)
59+
.style('stroke', O.theme.strokeColor)
5360
.style('stroke-width', 1)
5461
.style('fill', fill)
5562
.attr('cx', O.rowHeight / 2)
@@ -67,7 +74,7 @@ const GEOMS = {
6774
.domain([column.min, column.min + column.range * O.midpoint])(value);
6875
const radius = (value * 0.9 + 0.12) * O.geomSize - O.geomPadding; // 0.5 for stroke
6976
return d3.create('svg:circle')
70-
.style('stroke', O.geomStroke)
77+
.style('stroke', O.theme.strokeColor)
7178
.style('stroke-width', 1)
7279
.style('fill', fill)
7380
.attr('cx', O.rowHeight / 2)
@@ -81,7 +88,7 @@ const GEOMS = {
8188
.domain([column.min + column.range * O.midpoint, column.max])(value);
8289
const cornerSize = (0.9 - 0.8 * value) * O.geomSize;
8390
return d3.create('svg:rect')
84-
.style('stroke', O.geomStroke)
91+
.style('stroke', O.theme.strokeColor)
8592
.style('stroke-width', 1)
8693
.style('fill', fill)
8794
.attr('x', O.geomPadding)
@@ -99,7 +106,7 @@ class FHeatmap {
99106
this.columnInfo = columnInfo;
100107
this.columnGroups = d3.index(columnGroups, group => group.group);
101108
this.palettes = palettes;
102-
this.options = {...DEFAULT_OPTIONS, ...options};
109+
this.options = _.merge(DEFAULT_OPTIONS, options);
103110
this.calculateOptions();
104111
this.svg = svg;
105112
}
@@ -116,7 +123,7 @@ class FHeatmap {
116123
.attr('height', O.rowHeight)
117124
.attr('x', 0)
118125
.attr('y', i * O.rowHeight)
119-
.attr('fill', i % 2 === 0 ? O.rowAlternatingBackground : 'white');
126+
.attr('fill', i % 2 === 0 ? O.theme.evenRowBackground : O.theme.oddRowBackground);
120127
});
121128
}
122129

@@ -169,7 +176,7 @@ class FHeatmap {
169176
.attr('x2', offset + maxWidth)
170177
.attr('y1', 0)
171178
.attr('y2', O.bodyHeight)
172-
.attr('stroke', O.geomStroke)
179+
.attr('stroke', O.theme.strokeColor)
173180
.attr('stroke-dasharray', '5 5')
174181
.attr('opacity', 0.5);
175182
}
@@ -222,7 +229,7 @@ class FHeatmap {
222229
.attr('y', O.rowHeight / 2)
223230
.attr('text-anchor', 'middle')
224231
.attr('dominant-baseline', 'central')
225-
.attr('fill', 'white')
232+
.attr('fill', O.theme.headerColor)
226233
.text(groupInfo.name);
227234
if (O.fontSize) {
228235
text.attr('font-size', O.fontSize);
@@ -233,7 +240,7 @@ class FHeatmap {
233240
.attr('x', groupStart + O.padding)
234241
.attr('y', O.rowHeight / 2)
235242
.attr('dominant-baseline', 'central')
236-
.attr('fill', 'white')
243+
.attr('fill', O.theme.headerColor)
237244
.text(`${letter})`);
238245
if (O.fontSize) {
239246
text.attr('font-size', O.fontSize);
@@ -243,20 +250,24 @@ class FHeatmap {
243250
});
244251

245252
this.columnInfo.forEach(column => {
246-
const el = labels.append("g")
247-
.attr("transform", `rotate(${-O.columnRotate})`)
253+
const el = labels.append('g')
254+
.attr('transform', `rotate(${-O.columnRotate})`)
248255
.classed(`column-${column.id}`, true);
249-
el.append("text")
250-
.attr("x", 0)
251-
.attr("y", 0)
256+
el.append('text')
257+
.attr('x', 0)
258+
.attr('y', 0)
252259
.attr('font-size', O.fontSize)
260+
.style('fill', O.theme.textColor)
253261
.style('cursor', 'pointer')
254262
.datum(column)
255263
.on('click', this.onColumnClick.bind(this))
256264
.on('mouseenter', () => {
257-
el.style('text-decoration', 'underline dashed').style('fill', '#1385cb')
265+
el.style('text-decoration', 'underline dashed')
266+
.style('fill', O.theme.hoverColor)
267+
})
268+
.on('mouseleave', () => {
269+
el.style('text-decoration', '').style('fill', O.theme.textColor)
258270
})
259-
.on('mouseleave', () => el.style('text-decoration', '').style('fill', ''))
260271
.text(column.name);
261272
const nativeWidth = el.node().getBBox().width;
262273
if (!nonZeroRotate && nativeWidth < column.width - 2 * O.padding) {
@@ -290,7 +301,7 @@ class FHeatmap {
290301
.attr('x2', center)
291302
.attr('y1', headerHeight - 2)
292303
.attr('y2', headerHeight - 2 - O.padding)
293-
.attr('stroke', O.geomStroke);
304+
.attr('stroke', O.theme.strokeColor);
294305
}
295306
});
296307
this.options.width = bodyWidth;
@@ -314,6 +325,7 @@ class FHeatmap {
314325
.attr('x', offset + O.geomSize / 2)
315326
.attr('y', O.rowHeight + O.padding)
316327
.attr('font-size', O.legendFontSize)
328+
.style('fill', O.theme.textColor)
317329
.text('Score:');
318330

319331
const column = new Column({
@@ -332,7 +344,7 @@ class FHeatmap {
332344
`translate(${offset}, ${1.5 * O.rowHeight - height / 2})`
333345
);
334346
if (O.colorByRank) {
335-
el.style('fill', 'white');
347+
el.style('fill', O.theme.oddRowBackground);
336348
}
337349
let tick = parseFloat(i.toFixed(3));
338350
if (O.legendTicks.indexOf(tick) > -1) {
@@ -349,6 +361,7 @@ class FHeatmap {
349361
.attr('font-size', O.legendFontSize)
350362
.attr('text-anchor', 'middle')
351363
.attr('dominant-baseline', 'text-top')
364+
.style('fill', O.theme.textColor)
352365
.text(tick);
353366
}
354367
offset += width + 4 * O.geomPadding;
@@ -381,7 +394,7 @@ class FHeatmap {
381394
.style("border", "solid")
382395
.style("border-width", "1px")
383396
.style("border-radius", "5px")
384-
.style("padding", "10px")
397+
.style("padding", "8px 5px")
385398
.style("display", "none");
386399
}
387400

@@ -430,7 +443,7 @@ class FHeatmap {
430443
if (this.sortIndicator === undefined) {
431444
this.sortIndicator = this.header.append("text")
432445
.attr('font-size', 12)
433-
.attr('fill', '#1385cb');
446+
.attr('fill', O.theme.hoverColor);
434447
}
435448
if (column.sortState === "asc") {
436449
this.sortIndicator.text('↑');
@@ -506,7 +519,7 @@ function funkyheatmap(
506519
colAnnotOffset,
507520
addAbc,
508521
scaleColumn = true,
509-
options
522+
options = {}
510523
) {
511524
[data, columnInfo, columnGroups] = maybeConvertDataframe(data, columnInfo, columnGroups);
512525
columnInfo = buildColumnInfo(data, columns, columnInfo, scaleColumn, options.colorByRank);

test/full.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<h1>A JavaScript project</h1>
1010
<div id="app"></div>
1111
<script type="text/javascript" src="https://unpkg.com/d3@7.8.2/dist/d3.min.js"></script>
12+
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
1213
<script type="module" src="test-full.js"></script>
1314
</body>
1415
</html>

test/simple.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<h1>A JavaScript project</h1>
1010
<div id="app"></div>
1111
<script type="text/javascript" src="https://unpkg.com/d3@7.8.2/dist/d3.min.js"></script>
12+
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
1213
<script type="module" src="test.js"></script>
1314
</body>
1415
</html>

0 commit comments

Comments
 (0)