mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
Painting UI extras (#31699)
* Template width, offset, and import error messages * Grid toggle * oops, missing <br>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
//--------------------------------
|
||||
// Tab selector
|
||||
// Buttons, tabs, UI and misc.
|
||||
//--------------------------------
|
||||
var panelIdList = ["infoPanel", "templatePanel", "exportPanel"];
|
||||
function panelSelect(panelId) {
|
||||
@@ -38,12 +38,20 @@ function toggleHelp(helpButton, helpPanel) {
|
||||
toggleClass(helpPanel, "hidden");
|
||||
}
|
||||
|
||||
function toggleGrid() {
|
||||
grid_enabled = !grid_enabled;
|
||||
display_bitmap();
|
||||
toggleClass("grid_button", "linkOn");
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
// Template control
|
||||
//--------------------------------
|
||||
var currentTemplate = {};
|
||||
var currentTemplate = {ox:0, oy:0};
|
||||
/* A test template for 14x14 sized paintings
|
||||
{
|
||||
"w":14,
|
||||
"h":14,
|
||||
"rgn":[
|
||||
{"clr":"#ffffff","txt":"Mask"},
|
||||
{"clr":"#ffdddd","txt":"Mask border"},
|
||||
@@ -74,6 +82,7 @@ var currentTemplate = {};
|
||||
}
|
||||
*/
|
||||
|
||||
// Moves template color regions from/to "pending" and "done" lists
|
||||
function templateMover(id, isTargetToDone) {
|
||||
var item = document.getElementById("tp-" + id);
|
||||
|
||||
@@ -109,15 +118,11 @@ function templateMover(id, isTargetToDone) {
|
||||
if (!inserted) document.getElementById(target).insertAdjacentElement("beforeend", item);
|
||||
}
|
||||
|
||||
// Shorthand for templateMover()
|
||||
function templatePending(id) { templateMover(id, false); }
|
||||
function templateDone(id) { templateMover(id, true); }
|
||||
|
||||
function templatePending(id) {
|
||||
templateMover(id, false);
|
||||
}
|
||||
|
||||
function templateDone(id) {
|
||||
templateMover(id, true);
|
||||
}
|
||||
|
||||
// Builds color region items for the pending/done region list in the templates tab
|
||||
var colorRegex = /^#[0-9A-Fa-f]{6}$/;
|
||||
function buildTemplateItem(id, colorHint, textHint) {
|
||||
// Create a new color region element
|
||||
@@ -127,7 +132,7 @@ function buildTemplateItem(id, colorHint, textHint) {
|
||||
|
||||
// Color hint. Invalid colors get a red cross over a white background instead
|
||||
var missingColorIcon = "";
|
||||
if (!colorRegex.test(colorHint)) {
|
||||
if (!colorHint || !colorRegex.test(colorHint)) {
|
||||
missingColorIcon = '<span style="color: #ff0000; font-weight: bold">X</span>';
|
||||
colorHint = "#ffffff";
|
||||
}
|
||||
@@ -164,8 +169,119 @@ function buildTemplateItem(id, colorHint, textHint) {
|
||||
|
||||
}
|
||||
|
||||
// Paints the specified color region with the current color and opacity
|
||||
function templatePaint(id) {
|
||||
for (i in currentTemplate.bmp) {
|
||||
if (currentTemplate.bmp[i] == id) {
|
||||
var x = i % currentTemplate.w;
|
||||
var y = (i - x)/currentTemplate.w;
|
||||
x += currentTemplate.ox;
|
||||
y -= currentTemplate.oy;
|
||||
if (x >= 0 && x < width && y >= 0 && y < height)
|
||||
pixelDraw(x, y, getPaintColor(), getOpacity());
|
||||
}
|
||||
}
|
||||
display_bitmap();
|
||||
document.getElementById("bitmap").value = bitmap;
|
||||
}
|
||||
|
||||
// Manipulate template offset along the X axis
|
||||
function setTemplateOffsetX() {
|
||||
var input = document.getElementById("template_offset_X");
|
||||
currentTemplate.ox = parseInt(input.value);
|
||||
currentTemplate.ox = isNaN(currentTemplate.ox) ? 0 : currentTemplate.ox;
|
||||
input.value = currentTemplate.ox;
|
||||
}
|
||||
|
||||
function changeTemplateOffsetX(diff) {
|
||||
var input = document.getElementById("template_offset_X");
|
||||
currentTemplate.ox += diff ? diff : 0;
|
||||
input.value = currentTemplate.ox;
|
||||
}
|
||||
|
||||
// Manipulate template offset along the Y axis
|
||||
function setTemplateOffsetY() {
|
||||
var input = document.getElementById("template_offset_Y");
|
||||
currentTemplate.oy = parseInt(input.value);
|
||||
currentTemplate.oy = isNaN(currentTemplate.oy) ? 0 : currentTemplate.oy;
|
||||
input.value = currentTemplate.oy;
|
||||
}
|
||||
|
||||
function changeTemplateOffsetY(diff) {
|
||||
var input = document.getElementById("template_offset_Y");
|
||||
currentTemplate.oy += diff ? diff : 0;
|
||||
input.value = currentTemplate.oy;
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
// Template import
|
||||
//--------------------------------
|
||||
|
||||
|
||||
// Returns the parsed template if succesful, throws an error message otherwise
|
||||
function parseTemplate(template) {
|
||||
// Check the template contains anything resembling a JSON
|
||||
var tmpTemplate = template.slice(template.indexOf('{'), template.lastIndexOf('}')+1);
|
||||
if (!tmpTemplate) throw "Input is gibberish and not a template";
|
||||
|
||||
// Attempt to parse the template
|
||||
try {
|
||||
tmpTemplate = JSON.parse(tmpTemplate);
|
||||
} catch(e) {
|
||||
throw "Template could not be parsed:<span style=\"font-style:italic\">" + e.message.slice(e.message.indexOf(':')+1)+"</span>";
|
||||
}
|
||||
|
||||
// Check template contains a valid "rgn"
|
||||
if (!tmpTemplate.rgn) throw "Template is missing <code>\"rgn\"</code> parameter.";
|
||||
if (!Array.isArray(tmpTemplate.rgn) || !tmpTemplate.rgn.length) throw "<code>\"rgn\"</code> parameter is empty or not an array.";
|
||||
|
||||
// Check template contains a valid "bmp"
|
||||
if (!tmpTemplate.bmp) throw "Template is missing <code>\"bmp\"</code> parameter.";
|
||||
if (!Array.isArray(tmpTemplate.bmp) || !tmpTemplate.bmp.length) throw "<code>\"bmp\"</code> parameter is empty or not an array.";
|
||||
return tmpTemplate;
|
||||
}
|
||||
|
||||
// Detects any potential issues with the template and returns the appropiate message, returns an empty string if no issues are found
|
||||
function lintTemplate(template) {
|
||||
if (!template.w && (template.bmp.length % width) != 0)
|
||||
return "Note: Template bitmap (" + template.bmp.length + "px) does not match canvas width (" + width + "px), deformation is likely. ";
|
||||
if (!template.w && template.bmp.length != (height * width))
|
||||
return "Note: Template bitmap (" + template.bmp.length + "px) does not match canvas size (" + width + "x" + height + " = "+ width * height + "px)";
|
||||
if (template.w && (template.bmp.length % template.w) != 0)
|
||||
return "Note: Template bitmap (" + template.bmp.length + "px) does not match template width (" + template.w + "px), deformation is likely";
|
||||
if (template.w && template.h && template.bmp.length != (template.w * template.h))
|
||||
return "Note: Template bitmap (" + template.bmp.length + "px) does not match template size (" + template.w + "x" + template.h + " = "+ template.w * template.h + "px), height may be incorrect";
|
||||
if (template.w && template.w > width || template.h && template.h > height)
|
||||
return "Note: Template (" + (template.w ? template.w : "??") + "x" + (template.h ? template.h : "??") + ") will not fit canvas (" + width + "x" + height + ")";
|
||||
}
|
||||
|
||||
// Loads a template
|
||||
function loadTemplate(template) {
|
||||
//Empty both Pending and Done lists
|
||||
// Hide error messages
|
||||
document.getElementById("template_import_errors").style.display = "none";
|
||||
document.getElementById("template_import_warnings").style.display = "none";
|
||||
|
||||
// Parse template
|
||||
if (!template) return;
|
||||
var tmpTemplate;
|
||||
try {
|
||||
tmpTemplate = parseTemplate(template);
|
||||
} catch (msg) {
|
||||
// Display error message
|
||||
document.getElementById("template_import_errors").style.display = "block";
|
||||
document.getElementById("template_import_errors").innerHTML = msg;
|
||||
return;
|
||||
}
|
||||
currentTemplate = tmpTemplate;
|
||||
|
||||
// Warn the user of any potential issues
|
||||
var warning = lintTemplate(currentTemplate);
|
||||
if (warning) {
|
||||
document.getElementById("template_import_warnings").style.display = "block";
|
||||
document.getElementById("template_import_warnings").innerHTML = warning;
|
||||
}
|
||||
|
||||
// Empty both Pending and Done lists
|
||||
var itemLister = document.getElementById("doneRegions");
|
||||
while (itemLister.childElementCount > 0) {
|
||||
itemLister.removeChild(itemLister.firstChild);
|
||||
@@ -176,16 +292,43 @@ function loadTemplate(template) {
|
||||
}
|
||||
|
||||
// Fill Pending list with new color regions
|
||||
currentTemplate = JSON.parse(template);
|
||||
for (i = 0; i < currentTemplate.rgn.length; i++) {
|
||||
itemLister.appendChild(buildTemplateItem(i, currentTemplate.rgn[i].clr, currentTemplate.rgn[i].txt));
|
||||
}
|
||||
|
||||
// Set up template size display
|
||||
if (currentTemplate.w || currentTemplate.h) {
|
||||
document.getElementById("template_size").style.display = "block";
|
||||
document.getElementById("template_width").innerHTML = currentTemplate.w ? currentTemplate.w : "??";
|
||||
document.getElementById("template_height").innerHTML = currentTemplate.h ? currentTemplate.h : "??";
|
||||
} else {
|
||||
document.getElementById("template_size").style.display = "none";
|
||||
}
|
||||
|
||||
// Set up default template width to canvas width if missing
|
||||
currentTemplate.w = currentTemplate.w ? currentTemplate.w : width;
|
||||
|
||||
// Set up initial template offset, if missing
|
||||
currentTemplate.ox = currentTemplate.ox ? currentTemplate.ox : 0;
|
||||
currentTemplate.oy = currentTemplate.oy ? currentTemplate.oy : 0;
|
||||
|
||||
changeTemplateOffsetX();
|
||||
changeTemplateOffsetY();
|
||||
|
||||
// Open up the template tab and save the user that extra click
|
||||
panelSelect('templatePanel');
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
// Template export
|
||||
//--------------------------------
|
||||
|
||||
// Exports the current bitmap as a template
|
||||
function exportTemplate() {
|
||||
var output = document.getElementById("export-text");
|
||||
var template = {rgn: [], bmp: []};
|
||||
|
||||
|
||||
// Build basic template
|
||||
var template = {w: width, h: height, rgn: [], bmp: []};
|
||||
var colors = [];
|
||||
for (pixel in bitmap) {
|
||||
if (colors.indexOf(bitmap[pixel]) < 0) {
|
||||
@@ -197,18 +340,6 @@ function exportTemplate() {
|
||||
output.value = JSON.stringify(template);
|
||||
}
|
||||
|
||||
function templatePaint(id) {
|
||||
for (i in currentTemplate.bmp) {
|
||||
if (currentTemplate.bmp[i] == id) {
|
||||
var x = i % width;
|
||||
var y = (i - x)/width;
|
||||
pixelDraw(x, y, getPaintColor(), getOpacity());
|
||||
}
|
||||
}
|
||||
display_bitmap();
|
||||
document.getElementById("bitmap").value = bitmap;
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
// INIT
|
||||
//--------------------------------
|
||||
@@ -221,6 +352,9 @@ function initCanvas(paintInitData, canvasInitData) {
|
||||
canvasInitData = JSON.parse(canvasInitData);
|
||||
|
||||
src = canvasInitData.src;
|
||||
document.getElementById("canvas_width").innerHTML = width;
|
||||
document.getElementById("canvas_height").innerHTML = height;
|
||||
|
||||
document.getElementById("title").value = canvasInitData.title;
|
||||
document.getElementById("author").value = canvasInitData.author;
|
||||
document.getElementById("description").value = canvasInitData.description;
|
||||
@@ -237,7 +371,7 @@ function initCanvas(paintInitData, canvasInitData) {
|
||||
|
||||
for (color in palette) {
|
||||
paletteButtonPanel.innerHTML +=
|
||||
'<div class="paletteColor" onclick="setColor(\'' + palette[color] + '\');" style="background-image:' + generateColorPaletteBackgroundStyle(palette[color]) + '; background-image:' + generateColorPaletteBackgroundStyle(palette[color], true) + '"></div>\n';
|
||||
'<div class="paletteColor" onclick="setColor(\'' + palette[color] + '\');" style="background-image:' + generateColorPaletteBackgroundStyle(palette[color]) + '; background-image:' + generateColorPaletteBackgroundStyle(palette[color], true) + '"></div>\n';
|
||||
}
|
||||
setColor(palette[0]);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
|
||||
<!-- Info panel -->
|
||||
<div id="infoPanel" class="">
|
||||
<div class="item">
|
||||
<label class="itemLabelNarrow">Size: </label>
|
||||
<span id="canvas_width">??</span>x<span id="canvas_height">??</span>
|
||||
</div><br>
|
||||
<div>
|
||||
<label class="itemLabel">Title: </label><br/>
|
||||
<input
|
||||
@@ -63,29 +67,32 @@
|
||||
<div id="exportPanel" class="hidden">
|
||||
<div class="line"><a id="importHelpButton" class="button" onclick="toggleHelp('importHelpButton', 'importHelp');">Help</a></div><br/>
|
||||
<div id="importHelp" class="hidden block">
|
||||
<p>Templates define a number of same-color regions, and assigns each pixel on your painting to a region, allowing you to use the "<i>Template</i>" tab to paint faster.</p>
|
||||
<p>Templates are formatted as a <i>JSON</i>, using the following pattern:</p>
|
||||
<code>{"rgn":[<br>
|
||||
{"clr":"#ff0000","txt":"A"},<br>
|
||||
{"clr":"#00ff00","txt":"B"},<br>
|
||||
{"clr":"#0000ff","txt":""}<br>
|
||||
], "bmp": [1,0,1,2]}</code>
|
||||
<p>The first list (<code>"rgn"</code>) is a list of regions, each defining an hexadecimal RGB color hint (<code>"clr"</code>), and some text (<code>"txt"</code>).</p>
|
||||
<p>The second list (<code>"bmp"</code>) assigns a region to each pixel, identified by their position on the <code>"rgn"</code> list: Pixels assigned to the first region will be marked with a "0", pixels assigned to the second with a "1", pixels assigned with to the third with a "2", and so on.</p>
|
||||
<p>Make sure the size of your painting's canvas matches that of the template's bitmap! A 14x14 template will look distorted on a 26x26 canvas.</p>
|
||||
<p>You may also export your current painting as a template, but be aware it may result in dozens of regions, and they will not be given any description</p>
|
||||
<p>Templates define a number of same-color regions, and assigns each pixel on your painting to a region, allowing you to use the "<i>Template</i>" tab to paint faster.</p>
|
||||
<p>Templates are formatted as <i>JSON</i> objects, using the following pattern:</p>
|
||||
<code>{"w":2,"h":2,"rgn":[<br>
|
||||
{"clr":"#ff0000","txt":"A"},<br>
|
||||
{"clr":"#00ff00","txt":"B"},<br>
|
||||
{"clr":"#0000ff","txt":""}<br>
|
||||
], "bmp": [1,0,1,2]}</code>
|
||||
<p>The first list (<code>"rgn"</code>) is a list of regions, each defining an hexadecimal RGB color hint (<code>"clr"</code>), and some text (<code>"txt"</code>).</p>
|
||||
<p>The second list (<code>"bmp"</code>) assigns a region to each pixel, identified by their position on the <code>"rgn"</code> list: Pixels assigned to the first region will be marked with a "0", pixels assigned to the second with a "1", pixels assigned to the third with a "2", and so on.</p>
|
||||
<p>The optional parameters <code>"w"</code> and <code>"h"</code> indicate the width and height of the template. Providing a width allows templates to retain their shape if used on a canvas size they weren't meant for, otherwise using a 14x14 template will look distorted on a 24x24 canvas. Specifying height does nothing, but can be useful to other players</p>
|
||||
<p>The optional parameters <code>"ox"</code> and <code>"oy"</code> indicate the default offset of the template along the X and Y axes respectively, and are rarely needed.</p>
|
||||
<p>You may also export your current painting as a template, but be aware it may result in dozens of regions, and they will not be given any description</p>
|
||||
</div><br/>
|
||||
|
||||
<h3>Import</h3>
|
||||
<div>
|
||||
<textarea id="import-text" rows="5"></textarea>
|
||||
<a class="button" onclick="loadTemplate(document.getElementById('import-text').value)">Import template</a><br/>
|
||||
</div><br/>
|
||||
</div>
|
||||
<!-- Error messages -->
|
||||
<div class="item" id="template_import_errors" style="display:none"></div><br/>
|
||||
|
||||
<h3>Export</h3>
|
||||
<div>
|
||||
<textarea id="export-text" rows="5"></textarea>
|
||||
<a class="button" onclick="exportTemplate()">Export painting</a>
|
||||
<a class="button" onclick="exportTemplate()">Export painting as template</a>
|
||||
</div><br/>
|
||||
</div>
|
||||
|
||||
@@ -93,11 +100,40 @@
|
||||
<div id="templatePanel" class="hidden">
|
||||
<div class="line"><a id="templateHelpButton" class="button" onclick="toggleHelp('templateHelpButton', 'templateHelp');">Help</a></div><br/>
|
||||
<div id="templateHelp" class="block hidden">
|
||||
<p>Use the "<i>Import</i>" tab to import a painting template, a list of regions meant to have the same color that will be displayed on this tab.</p>
|
||||
<p>Use "<i>Paint Over</i>" to paint a given region with your currently selected color and opacity. Each region usually comes with a color hint you're meant to match (color square to the left of "<i>Paint Over</i>"), and hopefully some text explaining what each region is meant to be (info button).</p>
|
||||
<p>You may move any region to "<i>Done</i>" at any time, so as to get it out of the way if you're done with it, or back to "<i>In Progress</i>" if you need to touch it up again.</p>
|
||||
</div><br/>
|
||||
|
||||
<p>Use the "<i>Import</i>" tab to import a painting template, a list of regions meant to have the same color that will be displayed on this tab.</p>
|
||||
<p>Use the "<i>X</i>" and "<i>Y</i>" controls to reposition the template template along either axis. An offset of (0, 0) will position the top left corner of the template at the top left corner of the canvas.</p>
|
||||
<p>Use "<i>Paint Over</i>" to paint a given region with your currently selected color and opacity. Each region usually comes with a color hint you're meant to match (color square to the left of "<i>Paint Over</i>"), and hopefully some text explaining what each region is meant to be (info button).</p>
|
||||
<p>You may move any region to "<i>Done</i>" at any time, so as to get it out of the way if you're done with it, or back to "<i>In Progress</i>" if you need to touch it up again.</p>
|
||||
</div>
|
||||
|
||||
<h3>Info</h3>
|
||||
<!-- Template Size -->
|
||||
<div class="item" id="template_size" style="display: none">
|
||||
<label class="itemLabelNarrow">Size: </label>
|
||||
<span id="template_width">??</span>x<span id="template_height">??</span>
|
||||
</div>
|
||||
<!-- X Offset -->
|
||||
<div class="item toolPanel">
|
||||
<label class="itemLabelNarrow">X: </label>
|
||||
<a id="template_offset_X_decrease" class="button" onclick="changeTemplateOffsetX(-1);"><div class="uiIcon16 icon-minus"></div></a>
|
||||
<span class="statusValue">
|
||||
<input type="text" id="template_offset_X" value="0" onchange="setTemplateOffsetX();"/>
|
||||
</span>
|
||||
<a id="template_offset_X_increase" class="button" onclick="changeTemplateOffsetX(1);"><div class="uiIcon16 icon-plus"></div></a>
|
||||
</div>
|
||||
<!-- Y Offset -->
|
||||
<div class="item toolPanel">
|
||||
<label class="itemLabelNarrow">Y: </label>
|
||||
<a id="template_offset_Y_decrease" class="button" onclick="changeTemplateOffsetY(-1);"><div class="uiIcon16 icon-minus"></div></a>
|
||||
<span class="statusValue">
|
||||
<input type="text" id="template_offset_Y" value="0" onchange="setTemplateOffsetY();"/>
|
||||
</span>
|
||||
<a id="template_offset_Y_increase" class="button" onclick="changeTemplateOffsetY(1);"><div class="uiIcon16 icon-plus"></div></a>
|
||||
</div>
|
||||
<!-- Warning messages -->
|
||||
<div class="item" id="template_import_warnings" style="display:none"></div>
|
||||
|
||||
<!-- Color region lists -->
|
||||
<h3>In Progress</h3>
|
||||
<ul id="pendingRegions">
|
||||
</ul>
|
||||
@@ -126,17 +162,18 @@
|
||||
<!-- Paint Tool Controls -->
|
||||
<div class="paintPanel">
|
||||
<div class="item">
|
||||
<span class="toolPanel">
|
||||
<label class="itemLabelNarrow">Opacity: </label>
|
||||
<a id="paint_strength_lower" class="button" onclick="changeStrength(-0.05);"><div class="uiIcon16 icon-minus"></div></a>
|
||||
<span class="statusValue" id="tool_data_inputs">
|
||||
<!-- Example. Replace with actual value using "interface.updateContent(...)"; -->
|
||||
<input type="hidden" id="min_paint_strength" value="0"/>
|
||||
<input type="hidden" id="max_paint_strength" value="1"/>
|
||||
<input type="text" id="paint_strength" value="0.5" onchange="setStrength();"/>
|
||||
</span>
|
||||
<a id="paint_strength_lower" class="button" onclick="changeStrength(0.05);"><div class="uiIcon16 icon-plus"></div></a>
|
||||
</span>
|
||||
<span class="toolPanel item">
|
||||
<label class="itemLabelNarrow">Opacity: </label>
|
||||
<a id="paint_strength_decrease" class="button" onclick="changeStrength(-0.05);"><div class="uiIcon16 icon-minus"></div></a>
|
||||
<span class="statusValue" id="tool_data_inputs">
|
||||
<!-- Example. Replace with actual value using "interface.updateContent(...)"; -->
|
||||
<input type="hidden" id="min_paint_strength" value="0"/>
|
||||
<input type="hidden" id="max_paint_strength" value="1"/>
|
||||
<input type="text" id="paint_strength" value="0.5" onchange="setStrength();"/>
|
||||
</span>
|
||||
<a id="paint_strength_increase" class="button" onclick="changeStrength(0.05);"><div class="uiIcon16 icon-plus"></div></a>
|
||||
<a id="grid_button" class="button" onclick="toggleGrid();">Toggle grid</a>
|
||||
</span>
|
||||
</div>
|
||||
<!-- Selected Color -->
|
||||
<div class="item colorPanel">
|
||||
|
||||
@@ -87,6 +87,9 @@ var paint_opacity = 0.5;
|
||||
var minPaintStrength = 0;
|
||||
var maxPaintStrength = 1;
|
||||
|
||||
//Other options
|
||||
var grid_enabled = false;
|
||||
|
||||
// Milliseconds to wait since we last moved the mouse in ordder to draw.
|
||||
// Ensures all browsers draw lines with the same opacity, instead of letting those that check more often drawing darker lines
|
||||
const PAINT_TOOL_MOVEMENT_THROTTLE = 10;
|
||||
@@ -472,4 +475,24 @@ function display_bitmap() {
|
||||
ctx.fillRect(x*scaleX, y*scaleY, scaleX, scaleY);
|
||||
}
|
||||
}
|
||||
|
||||
if (grid_enabled) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.setLineDash([6,6]);
|
||||
for (var x = 0; x < width; x++) {
|
||||
ctx.moveTo(x*scaleX+0.5, 0.5);
|
||||
ctx.lineTo(x*scaleX+0.5, height*scaleY+0.5);
|
||||
}
|
||||
for (var y = 0; y < height; y++) {
|
||||
ctx.moveTo(0.5, y*scaleY+0.5);
|
||||
ctx.lineTo(width*scaleX+0.5, y*scaleY+0.5);
|
||||
}
|
||||
ctx.lineDashOffset = 0;
|
||||
ctx.strokeStyle = "#333333";
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = "#cccccc";
|
||||
ctx.lineDashOffset = 6;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user