[BUG] Colorbar thickness becomes too wide (~16k px) when marker.colorbar.thicknessmode='pixels' is applied via Plotly.restyle
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- JavaScript
- Star
- 18.3k
- Fork
- 2k
- Merge trung bình
- 2 ngày 12 giờ
- Pull request đã merge (30 ngày)
- 28
Mô tả
Description
For a splom trace whose marker.colorbar exists but has no explicit thickness
(plotly.js defaults it), applying marker.colorbar.thicknessmode='pixels' afterwards with
Plotly.restyle collapses the whole splom layout:
- plotly.js silently writes
thickness: 16290back into the user-visible trace
(gd.data[1].marker.colorbar.thickness), - the colorbar then occupies ~16k px and the splom panels shrink from ~125 px to ~15 px per axis.
Setting the exact same value at newPlot time (Path A in the repro) renders fine.
Reproduced on every version I could test: 2.35.2, 3.5.0, 3.5.1, and current 3.8.2.
Steps to reproduce
Save the following as index.html and open it in a browser
(uses https://cdn.plot.ly/plotly-3.5.0.min.js; the bundled copy from any release works too).
The page renders both paths, then prints the colorbar object and the panel width under each plot.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>plotly.js splom + marker.colorbar restyle bug</title>
<!-- any plotly.js >= 2.35 works: use your own bundle or the CDN below -->
<script src="https://cdn.plot.ly/plotly-3.5.0.min.js"></script>
<style>
body { font-family: -apple-system, "Segoe UI", Roboto, sans-serif; margin: 16px; }
.row { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; }
h3 { margin: 10px 0 4px; font-size: 15px; }
pre { background: #f6f8fa; border-radius: 6px; padding: 10px; font-size: 12px;
white-space: pre-wrap; max-width: 780px; }
code { background: #f6f8fa; padding: 1px 4px; border-radius: 4px; }
</style>
</head>
<body>
<h1>splom layout collapses when <code>marker.colorbar.thicknessmode='pixels'</code>
is applied with <code>Plotly.restyle</code></h1>
<p>Same data + layout, same final <code>marker.colorbar</code> value. Difference is only <b>when</b>
it is applied:</p>
<ul>
<li><b>Path A (normal):</b> <code>marker.colorbar = {thicknessmode: 'pixels'}</code> is in the
figure at <code>newPlot</code> time.</li>
<li><b>Path B (collapsed):</b> figure starts with <code>marker.colorbar = {}</code> (no explicit
<code>thickness</code>), then <code>Plotly.restyle(gd, {'marker.colorbar.thicknessmode':'pixels'}, [1])</code>.</li>
</ul>
<p>After Path B, plotly.js writes <b>thickness: 16290</b> back into the trace's colorbar and the
splom panels collapse from ~125px to ~15px per axis.</p>
<div class="row">
<div>
<h3>Path A — set at newPlot time (normal)</h3>
<div id="A" class="gd" style="width:750px;height:900px"></div>
<pre id="mA">…</pre>
</div>
<div>
<h3>Path B — set via Plotly.restyle (collapsed)</h3>
<div id="B" class="gd" style="width:750px;height:900px"></div>
<pre id="mB">…</pre>
</div>
</div>
<script>
var DATA = [{"dimensions": [{"axis": {"matches": true}, "label": "sepal_length", "values": {"dtype": "f8", "bdata": "ZmZmZmZmFECamZmZmZkTQM3MzMzMzBJAZmZmZmZmEkAAAAAAAAAUQJqZmZmZmRVAZmZmZmZmEkAAAAAAAAAUQJqZmZmZmRFAmpmZmZmZE0CamZmZmZkVQDMzMzMzMxNAMzMzMzMzE0AzMzMzMzMRQDMzMzMzMxdAzczMzMzMFkCamZmZmZkVQGZmZmZmZhRAzczMzMzMFkBmZmZmZmYUQJqZmZmZmRVAZmZmZmZmFEBmZmZmZmYSQGZmZmZmZhRAMzMzMzMzE0AAAAAAAAAUQAAAAAAAABRAzczMzMzMFEDNzMzMzMwUQM3MzMzMzBJAMzMzMzMzE0CamZmZmZkVQM3MzMzMzBRAAAAAAAAAFkCamZmZmZkTQAAAAAAAABRAAAAAAAAAFkCamZmZmZkTQJqZmZmZmRFAZmZmZmZmFEAAAAAAAAAUQAAAAAAAABJAmpmZmZmZEUAAAAAAAAAUQGZmZmZmZhRAMzMzMzMzE0BmZmZmZmYUQGZmZmZmZhJAMzMzMzMzFUAAAAAAAAAUQA=="}}, {"axis": {"matches": true}, "label": "sepal_width", "values": {"dtype": "f8", "bdata": "AAAAAAAADEAAAAAAAAAIQJqZmZmZmQlAzczMzMzMCEDNzMzMzMwMQDMzMzMzMw9AMzMzMzMzC0AzMzMzMzMLQDMzMzMzMwdAzczMzMzMCECamZmZmZkNQDMzMzMzMwtAAAAAAAAACEAAAAAAAAAIQAAAAAAAABBAmpmZmZmZEUAzMzMzMzMPQAAAAAAAAAxAZmZmZmZmDkBmZmZmZmYOQDMzMzMzMwtAmpmZmZmZDUDNzMzMzMwMQGZmZmZmZgpAMzMzMzMzC0AAAAAAAAAIQDMzMzMzMwtAAAAAAAAADEAzMzMzMzMLQJqZmZmZmQlAzczMzMzMCEAzMzMzMzMLQGZmZmZmZhBAzczMzMzMEEDNzMzMzMwIQJqZmZmZmQlAAAAAAAAADEDNzMzMzMwIQAAAAAAAAAhAMzMzMzMzC0AAAAAAAAAMQGZmZmZmZgJAmpmZmZmZCUAAAAAAAAAMQGZmZmZmZg5AAAAAAAAACEBmZmZmZmYOQJqZmZmZmQlAmpmZmZmZDUBmZmZmZmYKQA=="}}, {"axis": {"matches": true}, "label": "petal_length", "values": {"dtype": "f8", "bdata": "ZmZmZmZm9j9mZmZmZmb2P83MzMzMzPQ/AAAAAAAA+D9mZmZmZmb2PzMzMzMzM/s/ZmZmZmZm9j8AAAAAAAD4P2ZmZmZmZvY/AAAAAAAA+D8AAAAAAAD4P5qZmZmZmfk/ZmZmZmZm9j+amZmZmZnxPzMzMzMzM/M/AAAAAAAA+D/NzMzMzMz0P2ZmZmZmZvY/MzMzMzMz+z8AAAAAAAD4PzMzMzMzM/s/AAAAAAAA+D8AAAAAAADwPzMzMzMzM/s/ZmZmZmZm/j+amZmZmZn5P5qZmZmZmfk/AAAAAAAA+D9mZmZmZmb2P5qZmZmZmfk/mpmZmZmZ+T8AAAAAAAD4PwAAAAAAAPg/ZmZmZmZm9j8AAAAAAAD4PzMzMzMzM/M/zczMzMzM9D8AAAAAAAD4P83MzMzMzPQ/AAAAAAAA+D/NzMzMzMz0P83MzMzMzPQ/zczMzMzM9D+amZmZmZn5P2ZmZmZmZv4/ZmZmZmZm9j+amZmZmZn5P2ZmZmZmZvY/AAAAAAAA+D9mZmZmZmb2Pw=="}}, {"axis": {"matches": true}, "label": "petal_width", "values": {"dtype": "f8", "bdata": "mpmZmZmZyT+amZmZmZnJP5qZmZmZmck/mpmZmZmZyT+amZmZmZnJP5qZmZmZmdk/MzMzMzMz0z+amZmZmZnJP5qZmZmZmck/mpmZmZmZuT+amZmZmZnJP5qZmZmZmck/mpmZmZmZuT+amZmZmZm5P5qZmZmZmck/mpmZmZmZ2T+amZmZmZnZPzMzMzMzM9M/MzMzMzMz0z8zMzMzMzPTP5qZmZmZmck/mpmZmZmZ2T+amZmZmZnJPwAAAAAAAOA/mpmZmZmZyT+amZmZmZnJP5qZmZmZmdk/mpmZmZmZyT+amZmZmZnJP5qZmZmZmck/mpmZmZmZyT+amZmZmZnZP5qZmZmZmbk/mpmZmZmZyT+amZmZmZm5P5qZmZmZmck/mpmZmZmZyT+amZmZmZm5P5qZmZmZmck/mpmZmZmZyT8zMzMzMzPTPzMzMzMzM9M/mpmZmZmZyT8zMzMzMzPjP5qZmZmZmdk/MzMzMzMz0z+amZmZmZnJP5qZmZmZmck/mpmZmZmZyT+amZmZmZnJPw=="}}], "hovertemplate": "species=setosa<br>%{xaxis.title.text}=%{x}<br>%{yaxis.title.text}=%{y}<extra></extra>", "legendgroup": "setosa", "marker": {"color": "#636efa", "symbol": "circle"}, "name": "setosa", "showlegend": true, "type": "splom"}, {"dimensions": [{"axis": {"matches": true}, "label": "sepal_length", "values": {"dtype": "f8", "bdata": "AAAAAAAAHECamZmZmZkZQJqZmZmZmRtAAAAAAAAAFkAAAAAAAAAaQM3MzMzMzBZAMzMzMzMzGUCamZmZmZkTQGZmZmZmZhpAzczMzMzMFEAAAAAAAAAUQJqZmZmZmRdAAAAAAAAAGEBmZmZmZmYYQGZmZmZmZhZAzczMzMzMGkBmZmZmZmYWQDMzMzMzMxdAzczMzMzMGEBmZmZmZmYWQJqZmZmZmRdAZmZmZmZmGEAzMzMzMzMZQGZmZmZmZhhAmpmZmZmZGUBmZmZmZmYaQDMzMzMzMxtAzczMzMzMGkAAAAAAAAAYQM3MzMzMzBZAAAAAAAAAFkAAAAAAAAAWQDMzMzMzMxdAAAAAAAAAGECamZmZmZkVQAAAAAAAABhAzczMzMzMGkAzMzMzMzMZQGZmZmZmZhZAAAAAAAAAFkAAAAAAAAAWQGZmZmZmZhhAMzMzMzMzF0AAAAAAAAAUQGZmZmZmZhZAzczMzMzMFkDNzMzMzMwWQM3MzMzMzBhAZmZmZmZmFEDNzMzMzMwWQA=="}}, {"axis": {"matches": true}, "label": "sepal_width", "values": {"dtype": "f8", "bdata": "mpmZmZmZCUCamZmZmZkJQM3MzMzMzAhAZmZmZmZmAkBmZmZmZmYGQGZmZmZmZgZAZmZmZmZmCkAzMzMzMzMDQDMzMzMzMwdAmpmZmZmZBUAAAAAAAAAAQAAAAAAAAAhAmpmZmZmZAUAzMzMzMzMHQDMzMzMzMwdAzczMzMzMCEAAAAAAAAAIQJqZmZmZmQVAmpmZmZmZAUAAAAAAAAAEQJqZmZmZmQlAZmZmZmZmBkAAAAAAAAAEQGZmZmZmZgZAMzMzMzMzB0AAAAAAAAAIQGZmZmZmZgZAAAAAAAAACEAzMzMzMzMHQM3MzMzMzARAMzMzMzMzA0AzMzMzMzMDQJqZmZmZmQVAmpmZmZmZBUAAAAAAAAAIQDMzMzMzMwtAzczMzMzMCEBmZmZmZmYCQAAAAAAAAAhAAAAAAAAABEDNzMzMzMwEQAAAAAAAAAhAzczMzMzMBEBmZmZmZmYCQJqZmZmZmQVAAAAAAAAACEAzMzMzMzMHQDMzMzMzMwdAAAAAAAAABEBmZmZmZmYGQA=="}}, {"axis": {"matches": true}, "label": "petal_length", "values": {"dtype": "f8", "bdata": "zczMzMzMEkAAAAAAAAASQJqZmZmZmRNAAAAAAAAAEEBmZmZmZmYSQAAAAAAAABJAzczMzMzMEkBmZmZmZmYKQGZmZmZmZhJAMzMzMzMzD0AAAAAAAAAMQM3MzMzMzBBAAAAAAAAAEEDNzMzMzMwSQM3MzMzMzAxAmpmZmZmZEUAAAAAAAAASQGZmZmZmZhBAAAAAAAAAEkAzMzMzMzMPQDMzMzMzMxNAAAAAAAAAEECamZmZmZkTQM3MzMzMzBJAMzMzMzMzEUCamZmZmZkRQDMzMzMzMxNAAAAAAAAAFEAAAAAAAAASQAAAAAAAAAxAZmZmZmZmDkCamZmZmZkNQDMzMzMzMw9AZmZmZmZmFEAAAAAAAAASQAAAAAAAABJAzczMzMzMEkCamZmZmZkRQGZmZmZmZhBAAAAAAAAAEECamZmZmZkRQGZmZmZmZhJAAAAAAAAAEEBmZmZmZmYKQM3MzMzMzBBAzczMzMzMEEDNzMzMzMwQQDMzMzMzMxFAAAAAAAAACEBmZmZmZmYQQA=="}}, {"axis": {"matches": true}, "label": "petal_width", "values": {"dtype": "f8", "bdata": "ZmZmZmZm9j8AAAAAAAD4PwAAAAAAAPg/zczMzMzM9D8AAAAAAAD4P83MzMzMzPQ/mpmZmZmZ+T8AAAAAAADwP83MzMzMzPQ/ZmZmZmZm9j8AAAAAAADwPwAAAAAAAPg/AAAAAAAA8D9mZmZmZmb2P83MzMzMzPQ/ZmZmZmZm9j8AAAAAAAD4PwAAAAAAAPA/AAAAAAAA+D+amZmZmZnxP83MzMzMzPw/zczMzMzM9D8AAAAAAAD4PzMzMzMzM/M/zczMzMzM9D9mZmZmZmb2P2ZmZmZmZvY/MzMzMzMz+z8AAAAAAAD4PwAAAAAAAPA/mpmZmZmZ8T8AAAAAAADwPzMzMzMzM/M/mpmZmZmZ+T8AAAAAAAD4P5qZmZmZmfk/AAAAAAAA+D/NzMzMzMz0P83MzMzMzPQ/zczMzMzM9D8zMzMzMzPzP2ZmZmZmZvY/MzMzMzMz8z8AAAAAAADwP83MzMzMzPQ/MzMzMzMz8z/NzMzMzMz0P83MzMzMzPQ/mpmZmZmZ8T/NzMzMzMz0Pw=="}}], "hovertemplate": "species=versicolor<br>%{xaxis.title.text}=%{x}<br>%{yaxis.title.text}=%{y}<extra></extra>", "legendgroup": "versicolor", "marker": {"color": "#EF553B", "symbol": "circle"}, "name": "versicolor", "showlegend": true, "type": "splom"}, {"dimensions": [{"axis": {"matches": true}, "label": "sepal_length", "values": {"dtype": "f8", "bdata": "MzMzMzMzGUAzMzMzMzMXQGZmZmZmZhxAMzMzMzMzGUAAAAAAAAAaQGZmZmZmZh5AmpmZmZmZE0AzMzMzMzMdQM3MzMzMzBpAzczMzMzMHEAAAAAAAAAaQJqZmZmZmRlAMzMzMzMzG0DNzMzMzMwWQDMzMzMzMxdAmpmZmZmZGUAAAAAAAAAaQM3MzMzMzB5AzczMzMzMHkAAAAAAAAAYQJqZmZmZmRtAZmZmZmZmFkDNzMzMzMweQDMzMzMzMxlAzczMzMzMGkDNzMzMzMwcQM3MzMzMzBhAZmZmZmZmGECamZmZmZkZQM3MzMzMzBxAmpmZmZmZHUCamZmZmZkfQJqZmZmZmRlAMzMzMzMzGUBmZmZmZmYYQM3MzMzMzB5AMzMzMzMzGUCamZmZmZkZQAAAAAAAABhAmpmZmZmZG0DNzMzMzMwaQJqZmZmZmRtAMzMzMzMzF0AzMzMzMzMbQM3MzMzMzBpAzczMzMzMGkAzMzMzMzMZQAAAAAAAABpAzczMzMzMGECamZmZmZkXQA=="}}, {"axis": {"matches": true}, "label": "sepal_width", "values": {"dtype": "f8", "bdata": "ZmZmZmZmCkCamZmZmZkFQAAAAAAAAAhAMzMzMzMzB0AAAAAAAAAIQAAAAAAAAAhAAAAAAAAABEAzMzMzMzMHQAAAAAAAAARAzczMzMzMDECamZmZmZkJQJqZmZmZmQVAAAAAAAAACEAAAAAAAAAEQGZmZmZmZgZAmpmZmZmZCUAAAAAAAAAIQGZmZmZmZg5AzczMzMzMBECamZmZmZkBQJqZmZmZmQlAZmZmZmZmBkBmZmZmZmYGQJqZmZmZmQVAZmZmZmZmCkCamZmZmZkJQGZmZmZmZgZAAAAAAAAACEBmZmZmZmYGQAAAAAAAAAhAZmZmZmZmBkBmZmZmZmYOQGZmZmZmZgZAZmZmZmZmBkDNzMzMzMwEQAAAAAAAAAhAMzMzMzMzC0DNzMzMzMwIQAAAAAAAAAhAzczMzMzMCEDNzMzMzMwIQM3MzMzMzAhAmpmZmZmZBUCamZmZmZkJQGZmZmZmZgpAAAAAAAAACEAAAAAAAAAEQAAAAAAAAAhAMzMzMzMzC0AAAAAAAAAIQA=="}}, {"axis": {"matches": true}, "label": "petal_length", "values": {"dtype": "f8", "bdata": "AAAAAAAAGEBmZmZmZmYUQJqZmZmZmRdAZmZmZmZmFkAzMzMzMzMXQGZmZmZmZhpAAAAAAAAAEkAzMzMzMzMZQDMzMzMzMxdAZmZmZmZmGEBmZmZmZmYUQDMzMzMzMxVAAAAAAAAAFkAAAAAAAAAUQGZmZmZmZhRAMzMzMzMzFUAAAAAAAAAWQM3MzMzMzBpAmpmZmZmZG0AAAAAAAAAUQM3MzMzMzBZAmpmZmZmZE0DNzMzMzMwaQJqZmZmZmRNAzczMzMzMFkAAAAAAAAAYQDMzMzMzMxNAmpmZmZmZE0BmZmZmZmYWQDMzMzMzMxdAZmZmZmZmGECamZmZmZkZQGZmZmZmZhZAZmZmZmZmFEBmZmZmZmYWQGZmZmZmZhhAZmZmZmZmFkAAAAAAAAAWQDMzMzMzMxNAmpmZmZmZFUBmZmZmZmYWQGZmZmZmZhRAZmZmZmZmFECamZmZmZkXQM3MzMzMzBZAzczMzMzMFEAAAAAAAAAUQM3MzMzMzBRAmpmZmZmZFUBmZmZmZmYUQA=="}}, {"axis": {"matches": true}, "label": "petal_width", "values": {"dtype": "f8", "bdata": "AAAAAAAABEBmZmZmZmb+P83MzMzMzABAzczMzMzM/D+amZmZmZkBQM3MzMzMzABAMzMzMzMz+z/NzMzMzMz8P83MzMzMzPw/AAAAAAAABEAAAAAAAAAAQGZmZmZmZv4/zczMzMzMAEAAAAAAAAAAQDMzMzMzMwNAZmZmZmZmAkDNzMzMzMz8P5qZmZmZmQFAZmZmZmZmAkAAAAAAAAD4P2ZmZmZmZgJAAAAAAAAAAEAAAAAAAAAAQM3MzMzMzPw/zczMzMzMAEDNzMzMzMz8P83MzMzMzPw/zczMzMzM/D/NzMzMzMwAQJqZmZmZmfk/ZmZmZmZm/j8AAAAAAAAAQJqZmZmZmQFAAAAAAAAA+D9mZmZmZmb2P2ZmZmZmZgJAMzMzMzMzA0DNzMzMzMz8P83MzMzMzPw/zczMzMzMAEAzMzMzMzMDQGZmZmZmZgJAZmZmZmZm/j9mZmZmZmYCQAAAAAAAAARAZmZmZmZmAkBmZmZmZmb+PwAAAAAAAABAZmZmZmZmAkDNzMzMzMz8Pw=="}}], "hovertemplate": "species=virginica<br>%{xaxis.title.text}=%{x}<br>%{yaxis.title.text}=%{y}<extra></extra>", "legendgroup": "virginica", "marker": {"color": "#00cc96", "symbol": "circle"}, "name": "virginica", "showlegend": true, "type": "splom"}];
var LAYOUT = {"legend": {"title": {"text": "species"}, "tracegroupgap": 0}, "margin": {"t": 60}, "dragmode": "select", "xaxis": {"matches": "y"}, "xaxis2": {"matches": "y2"}, "xaxis3": {"matches": "y3"}, "xaxis4": {"matches": "y4"}, "height": 900, "width": 750, "selections": [{"x0": 3, "x1": 4, "xref": "x2", "y0": 8, "y1": 6, "yref": "y"}, {"x0": 5, "x1": 1, "xref": "x3", "y0": 5, "y1": 4, "yref": "y"}]};
function clone(o) { return JSON.parse(JSON.stringify(o)); }
function cb(gd) { return JSON.stringify(gd.data[1].marker.colorbar || {}); }
function ax(gd) { return gd._fullLayout.xaxis ? Math.round(gd._fullLayout.xaxis._length) + 'px' : '?'; }
function dump(gd, el) {
var cbs = gd.querySelectorAll('.colorbar');
var w = cbs.length ? Math.round(cbs[cbs.length-1].getBoundingClientRect().width) + 'px' : 'none';
el.textContent = 'trace1.marker.colorbar = ' + cb(gd) +
'\npanel width (xaxis._length) = ' + ax(gd) +
'\nrendered colorbar width = ' + w;
}
// Path A
var gdA = document.getElementById('A');
var dataA = clone(DATA);
dataA[1].marker.colorbar = { thicknessmode: 'pixels' };
Plotly.newPlot(gdA, dataA, clone(LAYOUT)).then(function () {
dump(gdA, document.getElementById('mA'));
});
// Path B
var gdB = document.getElementById('B');
var dataB = clone(DATA);
dataB[1].marker.colorbar = {};
Plotly.newPlot(gdB, dataB, clone(LAYOUT)).then(function () {
dump(gdB, document.getElementById('mB'));
return Plotly.restyle(gdB, { 'marker.colorbar.thicknessmode': 'pixels' }, [1]);
}).then(function () {
dump(gdB, document.getElementById('mB'));
});
</script>
</body>
</html>
Actual vs expected (measured with plotly 3.8.2, headless Chrome)
Path A (set at newPlot) |
Path B (set via restyle) |
|
|---|---|---|
trace[1].marker.colorbar after render |
{"thicknessmode":"pixels"} |
{"thickness":16290,"thicknessmode":"pixels"} |
panel width (_fullLayout.xaxis._length) |
125 px | 15 px |
| rendered colorbar width | 71 px | 16331 px |
Expected: Path B behaves like Path A — thickness defaulted to ~30 px for pixels mode,
panels stay 125 px.
(Note: with random synthetic splom data the exact numbers differ — e.g. thickness:17250,
axis len ~15 — but the collapse reproduces identically.)
Analysis
colorbar.thickness is size-dependent when left at its default: in fraction mode the
default is ~30 / plotHeight (a small fraction), converted to pixels only at calc time.
When Plotly.restyle flips thicknessmode to pixels on a colorbar that still holds the
fraction-mode default, the default is apparently not re-coerced for the new mode — the
old tiny fraction survives, is interpreted as raw pixels on the next colorbar calc, and the
result (~16k px) is also written back into gd.data (user-visible trace), not just
_fullLayout.
Evidence that fits this reading:
- Restyling
thicknesstogether withthicknessmode
({'marker.colorbar.thickness': 20, 'marker.colorbar.thicknessmode': 'pixels'}) works
fine — an explicit value bypasses the buggy default path. - After Path B, the wrong value is observable on the user data object
(gd.data[1].marker.colorbar.thickness === 16290), so a defaults-coercion result leaks
back intogd.data.
First reported at plotly/plotly.py#5615;
the plotly.py maintainers asked for a pure-JS reproduction here.
Workaround
Include an explicit thickness in the same restyle call:
Plotly.restyle(gd, {
'marker.colorbar.thicknessmode': 'pixels',
'marker.colorbar.thickness': 20
}, [1]);
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu bằng cách chạy bản tái hiện index.html được cung cấp với Plotly.newPlot và Plotly.restyle, sau đó truy vết cách marker.colorbar.thicknessmode được xử lý cho các trace splom. Hoàn thành nghĩa là việc áp dụng mode thông qua Plotly.restyle không còn ghi thickness: 16290 hoặc làm các panel bị thu gọn, trong khi đường đi newPlot vẫn đúng.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- javascript
- Lĩnh vực
- data-visualization, frontend
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 68/100