Canvas 边框不起作用以及如何向 canvas 添加潜台词
Canvas border not working and how to add subtext to canvas
我已经构建了一个简单的横幅创建工具 - 它基本上允许用户添加文本、应用 fonts/colors/font 大小、添加边框等。它主要工作但我无法将边框应用到新图像和应用潜台词。不仅不会出现边框,而且边框宽度在改变文字stroke/outline宽度
关于添加潜台词,我需要一个潜台词放在位于图像中心的正文(工作)下方。我需要副文本大约是正文大小的 20%。我下面的代码不包含任何子文本 - 因为在看到边框 lineWidth 与主文本混淆后,我担心任何子文本代码都会与主文本代码混淆。
#HTML
<div id="createBanner" class="form-row rowSpacing" style="display:none;">
<div class="form-row rowSpacing">
<div class="form-group col-md-5">
Select Banner Text:
<div style="margin-left:25px;">
<input type="radio" name="textType" id="textType1" value="1" onchange="buildBanner();" checked="checked"> <span id="bannerText1"></span> (Full Org Name)
<br><input type="radio" name="textType" id="textType2" value="2" onchange="buildBanner();" > <span id="bannerText2"></span> (Short Org Name)
</div>
</div>
</div>
<div class="form-row rowSpacing">
<div class="form-group col-md-5" style="display:block;">
<div>
<?php
helpButton($buttonID++,"Some browsers may not support all the listed fonts") ;
?>
Select Font:
<select id="fontFace" onchange="buildBanner();" >
<option selected value="Arial">Arial (sans-serif)</option>
<option value="Arial Black">Arial Black" (sans-serif)</option>
<option value="Verdana">Verdana (sans-serif)</option>
<option value="Tahoma">Tahoma (sans-serif)</option>
<option value="Trebuchet MS">Trebuchet MS (sans-serif)</option>
<option value="Impact">Impact (sans-serif)</option>
<option value="Times New Roman">Times New Roman (serif)</option>
<option value="Didot">Didot (serif)</option>
<option value="Georgia">Georgia (serif)</option>
<option value="American Typewriter">American Typewriter (serif)</option>
<option value="Andalé Mono">Andalé Mono (monospace)</option>
<option value="Courier">Courier (monospace)</option>
<option value="Lucida Console">Lucida Console (monospace)</option>
<option value="Monaco">Monaco (monospace)</option>
<option value="Bradley Hand">Bradley Hand (cursive)</option>
<option value="Brush Script MT">Brush Script MT (cursive)</option>
<option value="Luminari">Luminari (fantasy)</option>
<option value="Comic Sans MS">Comic Sans MS (cursive)</option>
</select>
</div>
<div style="margin-top:20px;">
Font Size: <input type="range" id="fontSize" min="25" max="200" step="1" onchange="buildBanner();" value="100"/>
</div>
<div style="margin-top:20px;">
Font Style:
<select id="fontStyle" onchange="buildBanner();" >
<option value="normal">Normal</option>
<option value="italic">Italic</option>
<option value="oblique">Oblique</option>
</select>
</div>
<div style="margin-top:20px;">
Font Weight:
<select id="fontWeight" onchange="buildBanner();" >
<option selected value="normal">Normal</option>
<option value="bold">Bold</option>
<option value="bolder">Bolder</option>
<option value="lighter">Lighter</option>
</select>
</div>
</div>
<div class="form-group col-md-5" style="display:block;">
<div>
Text Color Fill Type:
<select id="fillType" onchange="buildBanner();" >
<option selected value="colorFill">Color Fill</option>
<option value="linearGradient">Linear Gradient</option>
<option value="radialGradient">Radial Gradient</option>
</select>
</div>
<div style="margin-top:20px;">
Text Fill or Outline :
<select id="strokeType" onchange="buildBanner();" >
<option selected value="fill">Fill</option>
<option value="stroke">Outline</option>
</select>
</div>
<div style="margin-top:20px;">
If outline, line thickness: <input type="range" id="lineWidth" min="1" max="10" step="1" onchange="buildBanner();" value="2"/>
</div>
<div style="margin-top:20px;">
Text Color: <input type="color" id="textFillColor" onchange="buildBanner();" value="#000000"/>
</div>
</div>
</div>
<div class="form-row rowSpacing">
<div class="form-group col-md-5" style="display:block;">
<div>
Background Color: <input type="color" id="bgFillColor" onchange="buildBanner();" value="#ffffff"/>
</div>
<div style="margin-top:20px;">
Border width: <input type="range" id="borderWidth" min="0" max="10" step="1" onchange="buildBanner();" value="0"/>
</div>
<div style="margin-top:20px;">
Border Color: <input type="color" id="borderColor" onchange="buildBanner();" value="#000000"/>
</div>
</div>
</div>
<div style="">
<canvas id="realCanvas" width="1200" height="300" style="width:25vw;">
Your browser does not support Canvas.
</canvas>
<textarea id="imageDataDisplay" rows=5 cols=100 style="display:none;"></textarea>
</div>
</div>
#JS
function canvasSupport () {
return !!document.createElement("canvas").getContext;
}
function buildBanner () {
Debugger.log("Drawing Canvas");
if(!canvasSupport()) {
return;
}
var wCanvas = 1200 ;
var hCanvas = 300 ;
var realCanvas = document.getElementById('realCanvas');
var realContext = realCanvas.getContext('2d');
var text1 = document.getElementById('textType1') ;
var text2 = document.getElementById('textType2') ;
if (text1.checked) {
var bannerText = document.getElementById('cVendor').value ;
console.log("Text1: "+ bannerText) ;
} else if (text2.checked) {
var bannerText = document.getElementById('cVendorName').value ;
console.log("Text2: "+ bannerText) ;
}
var textStrokeColor = "#000000";
var textBaseline = "middle";
var textAlign = "center";
// This is the event handler for listening for a key up event in the text box form
// It will call the textBoxChanged function to update the text in the canvas
var fontSize = document.getElementById("fontSize").value;
var fontFaceSelect = document.getElementById("fontFace");
var fontFace = fontFaceSelect.options[fontFaceSelect.selectedIndex].value ;
var fontWeightSelect = document.getElementById("fontWeight");
var fontWeight = fontWeightSelect.options[fontWeightSelect.selectedIndex].value ;
var fontStyleSelect = document.getElementById("fontStyle");
var fontStyle = fontStyleSelect.options[fontStyleSelect.selectedIndex].value ;
var fillTypeSelect = document.getElementById("fillType");
var fillType = fillTypeSelect.options[fillTypeSelect.selectedIndex].value ;
var strokeTypeSelect = document.getElementById("strokeType");
var strokeType = strokeTypeSelect.options[strokeTypeSelect.selectedIndex].value ;
var strokeWidth = document.getElementById('strokeWidth').value ;
var borderColor = document.getElementById("borderColor").value ;
var borderWidth = document.getElementById("borderWidth").value ;
var textFillColor = document.getElementById("textFillColor").value ;
var bgFillColor = document.getElementById("bgFillColor").value ;
var imageData = document.getElementById("createImageData");
realContext = drawScreen(realContext,wCanvas,hCanvas,1);
var imageDataDisplay = document.getElementById("imageDataDisplay");
imageDataDisplay.value = realCanvas.toDataURL();
function drawScreen(thisContext,x,y,xSize) {
thisContext.clearRect(0, 0, x, y);
var metrics = thisContext.measureText(bannerText);
var textWidth = metrics.width;
var xPosition = x / 2
var yPosition = y / 2;
// Draws the Text Box
thisContext.globalAlpha = 1.0;
thisContext.fillStyle = bgFillColor ;
thisContext.fillRect(0,0,x,y);
if (borderWidth != 0) {
thisContext.strokeStyle = borderColor ;
thisContext.lineWidth = borderWidth ;
console.log(borderColor+ " : " +borderWidth) ;
thisContext.strokeRect(0, 0 , x-borderWidth, y-borderWidth) ;
}
// Draws the actual text
var xFontSize = fontSize * xSize ;
thisContext.font = fontWeight + " " + fontStyle + " " + xFontSize + "px " + fontFace;
thisContext.textBaseline = textBaseline;
thisContext.textAlign = textAlign;
var tempColor;
switch(fillType) {
case "colorFill":
Debugger.log("Color Fill");
tempColor = textFillColor;
break;
case "linearGradient":
Debugger.log("Linear Gradient");
var linGradient = thisContext.createLinearGradient(xPosition-textWidth/2, yPosition, xPosition+textWidth/2, yPosition);
linGradient.addColorStop(0, textFillColor);
tempColor = linGradient;
break;
case "radialGradient":
Debugger.log("Radial Gradient");
var radGradient = thisContext.createRadialGradient(xPosition, yPosition, 1, xPosition, yPosition, textWidth/2);
radGradient.addColorStop(0, textFillColor);
tempColor = radGradient;
break;
}
switch(strokeType) {
case "fill":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
break;
case "stroke":
thisContext.lineWidth = strokeWidth ;
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
case "both":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
}
return thisContext ;
}
}
您的代码中只有两个小错误。
#1 缺少边框
让我们看一下您的代码的以下部分:
if (borderWidth != 0) {
thisContext.strokeStyle = borderColor ;
thisContext.lineWidth = borderWidth ;
console.log(borderColor+ " : " +borderWidth) ;
thisContext.strokeRect(0, 0 , x-borderWidth, y-borderWidth) ;
}
//Add BACKGROUND color
thisContext.fillStyle = bgFillColor ;
thisContext.fillRect(0,0,x,y);
在这里我们可以看到您正在查询 borderWith
,如果它不是零,请画一个边框。所以在这一点上你肯定有一个边界。问题从下一段代码开始:
thisContext.fillRect(0,0,x,y);
这基本上会用当前的填充样式清除整个 canvas。您通常需要将其作为第一个绘图操作。例如
thisContext.globalAlpha = 1.0;
thisContext.fillStyle = bgFillColor;
thisContext.fillRect(0,0,x,y);
if (borderWidth != 0) {
thisContext.strokeStyle = borderColor ;
thisContext.lineWidth = borderWidth ;
console.log(borderColor+ " : " +borderWidth) ;
thisContext.strokeRect(0, 0 , x-borderWidth, y-borderWidth);
}
#2 边框宽度影响文字笔画
在此代码块中,我们可以看到文本的笔画由名为 lineWidth
的变量确定。
case "stroke":
thisContext.lineWidth = lineWidth ;
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
问题是:您没有那个名称的变量,所以它使用 ID 为 lineWidth 的 html <input>
元素,returns 废话和 canvas 将采用 thisContext.lineWidth
的最后一个值,即边框的粗细。
只需添加一个
var lineWidth = document.getElementById("lineWidth").value;
在 buildBanner()
函数的开头。
我已经构建了一个简单的横幅创建工具 - 它基本上允许用户添加文本、应用 fonts/colors/font 大小、添加边框等。它主要工作但我无法将边框应用到新图像和应用潜台词。不仅不会出现边框,而且边框宽度在改变文字stroke/outline宽度
关于添加潜台词,我需要一个潜台词放在位于图像中心的正文(工作)下方。我需要副文本大约是正文大小的 20%。我下面的代码不包含任何子文本 - 因为在看到边框 lineWidth 与主文本混淆后,我担心任何子文本代码都会与主文本代码混淆。
#HTML
<div id="createBanner" class="form-row rowSpacing" style="display:none;">
<div class="form-row rowSpacing">
<div class="form-group col-md-5">
Select Banner Text:
<div style="margin-left:25px;">
<input type="radio" name="textType" id="textType1" value="1" onchange="buildBanner();" checked="checked"> <span id="bannerText1"></span> (Full Org Name)
<br><input type="radio" name="textType" id="textType2" value="2" onchange="buildBanner();" > <span id="bannerText2"></span> (Short Org Name)
</div>
</div>
</div>
<div class="form-row rowSpacing">
<div class="form-group col-md-5" style="display:block;">
<div>
<?php
helpButton($buttonID++,"Some browsers may not support all the listed fonts") ;
?>
Select Font:
<select id="fontFace" onchange="buildBanner();" >
<option selected value="Arial">Arial (sans-serif)</option>
<option value="Arial Black">Arial Black" (sans-serif)</option>
<option value="Verdana">Verdana (sans-serif)</option>
<option value="Tahoma">Tahoma (sans-serif)</option>
<option value="Trebuchet MS">Trebuchet MS (sans-serif)</option>
<option value="Impact">Impact (sans-serif)</option>
<option value="Times New Roman">Times New Roman (serif)</option>
<option value="Didot">Didot (serif)</option>
<option value="Georgia">Georgia (serif)</option>
<option value="American Typewriter">American Typewriter (serif)</option>
<option value="Andalé Mono">Andalé Mono (monospace)</option>
<option value="Courier">Courier (monospace)</option>
<option value="Lucida Console">Lucida Console (monospace)</option>
<option value="Monaco">Monaco (monospace)</option>
<option value="Bradley Hand">Bradley Hand (cursive)</option>
<option value="Brush Script MT">Brush Script MT (cursive)</option>
<option value="Luminari">Luminari (fantasy)</option>
<option value="Comic Sans MS">Comic Sans MS (cursive)</option>
</select>
</div>
<div style="margin-top:20px;">
Font Size: <input type="range" id="fontSize" min="25" max="200" step="1" onchange="buildBanner();" value="100"/>
</div>
<div style="margin-top:20px;">
Font Style:
<select id="fontStyle" onchange="buildBanner();" >
<option value="normal">Normal</option>
<option value="italic">Italic</option>
<option value="oblique">Oblique</option>
</select>
</div>
<div style="margin-top:20px;">
Font Weight:
<select id="fontWeight" onchange="buildBanner();" >
<option selected value="normal">Normal</option>
<option value="bold">Bold</option>
<option value="bolder">Bolder</option>
<option value="lighter">Lighter</option>
</select>
</div>
</div>
<div class="form-group col-md-5" style="display:block;">
<div>
Text Color Fill Type:
<select id="fillType" onchange="buildBanner();" >
<option selected value="colorFill">Color Fill</option>
<option value="linearGradient">Linear Gradient</option>
<option value="radialGradient">Radial Gradient</option>
</select>
</div>
<div style="margin-top:20px;">
Text Fill or Outline :
<select id="strokeType" onchange="buildBanner();" >
<option selected value="fill">Fill</option>
<option value="stroke">Outline</option>
</select>
</div>
<div style="margin-top:20px;">
If outline, line thickness: <input type="range" id="lineWidth" min="1" max="10" step="1" onchange="buildBanner();" value="2"/>
</div>
<div style="margin-top:20px;">
Text Color: <input type="color" id="textFillColor" onchange="buildBanner();" value="#000000"/>
</div>
</div>
</div>
<div class="form-row rowSpacing">
<div class="form-group col-md-5" style="display:block;">
<div>
Background Color: <input type="color" id="bgFillColor" onchange="buildBanner();" value="#ffffff"/>
</div>
<div style="margin-top:20px;">
Border width: <input type="range" id="borderWidth" min="0" max="10" step="1" onchange="buildBanner();" value="0"/>
</div>
<div style="margin-top:20px;">
Border Color: <input type="color" id="borderColor" onchange="buildBanner();" value="#000000"/>
</div>
</div>
</div>
<div style="">
<canvas id="realCanvas" width="1200" height="300" style="width:25vw;">
Your browser does not support Canvas.
</canvas>
<textarea id="imageDataDisplay" rows=5 cols=100 style="display:none;"></textarea>
</div>
</div>
#JS
function canvasSupport () {
return !!document.createElement("canvas").getContext;
}
function buildBanner () {
Debugger.log("Drawing Canvas");
if(!canvasSupport()) {
return;
}
var wCanvas = 1200 ;
var hCanvas = 300 ;
var realCanvas = document.getElementById('realCanvas');
var realContext = realCanvas.getContext('2d');
var text1 = document.getElementById('textType1') ;
var text2 = document.getElementById('textType2') ;
if (text1.checked) {
var bannerText = document.getElementById('cVendor').value ;
console.log("Text1: "+ bannerText) ;
} else if (text2.checked) {
var bannerText = document.getElementById('cVendorName').value ;
console.log("Text2: "+ bannerText) ;
}
var textStrokeColor = "#000000";
var textBaseline = "middle";
var textAlign = "center";
// This is the event handler for listening for a key up event in the text box form
// It will call the textBoxChanged function to update the text in the canvas
var fontSize = document.getElementById("fontSize").value;
var fontFaceSelect = document.getElementById("fontFace");
var fontFace = fontFaceSelect.options[fontFaceSelect.selectedIndex].value ;
var fontWeightSelect = document.getElementById("fontWeight");
var fontWeight = fontWeightSelect.options[fontWeightSelect.selectedIndex].value ;
var fontStyleSelect = document.getElementById("fontStyle");
var fontStyle = fontStyleSelect.options[fontStyleSelect.selectedIndex].value ;
var fillTypeSelect = document.getElementById("fillType");
var fillType = fillTypeSelect.options[fillTypeSelect.selectedIndex].value ;
var strokeTypeSelect = document.getElementById("strokeType");
var strokeType = strokeTypeSelect.options[strokeTypeSelect.selectedIndex].value ;
var strokeWidth = document.getElementById('strokeWidth').value ;
var borderColor = document.getElementById("borderColor").value ;
var borderWidth = document.getElementById("borderWidth").value ;
var textFillColor = document.getElementById("textFillColor").value ;
var bgFillColor = document.getElementById("bgFillColor").value ;
var imageData = document.getElementById("createImageData");
realContext = drawScreen(realContext,wCanvas,hCanvas,1);
var imageDataDisplay = document.getElementById("imageDataDisplay");
imageDataDisplay.value = realCanvas.toDataURL();
function drawScreen(thisContext,x,y,xSize) {
thisContext.clearRect(0, 0, x, y);
var metrics = thisContext.measureText(bannerText);
var textWidth = metrics.width;
var xPosition = x / 2
var yPosition = y / 2;
// Draws the Text Box
thisContext.globalAlpha = 1.0;
thisContext.fillStyle = bgFillColor ;
thisContext.fillRect(0,0,x,y);
if (borderWidth != 0) {
thisContext.strokeStyle = borderColor ;
thisContext.lineWidth = borderWidth ;
console.log(borderColor+ " : " +borderWidth) ;
thisContext.strokeRect(0, 0 , x-borderWidth, y-borderWidth) ;
}
// Draws the actual text
var xFontSize = fontSize * xSize ;
thisContext.font = fontWeight + " " + fontStyle + " " + xFontSize + "px " + fontFace;
thisContext.textBaseline = textBaseline;
thisContext.textAlign = textAlign;
var tempColor;
switch(fillType) {
case "colorFill":
Debugger.log("Color Fill");
tempColor = textFillColor;
break;
case "linearGradient":
Debugger.log("Linear Gradient");
var linGradient = thisContext.createLinearGradient(xPosition-textWidth/2, yPosition, xPosition+textWidth/2, yPosition);
linGradient.addColorStop(0, textFillColor);
tempColor = linGradient;
break;
case "radialGradient":
Debugger.log("Radial Gradient");
var radGradient = thisContext.createRadialGradient(xPosition, yPosition, 1, xPosition, yPosition, textWidth/2);
radGradient.addColorStop(0, textFillColor);
tempColor = radGradient;
break;
}
switch(strokeType) {
case "fill":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
break;
case "stroke":
thisContext.lineWidth = strokeWidth ;
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
case "both":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
}
return thisContext ;
}
}
您的代码中只有两个小错误。
#1 缺少边框
让我们看一下您的代码的以下部分:
if (borderWidth != 0) {
thisContext.strokeStyle = borderColor ;
thisContext.lineWidth = borderWidth ;
console.log(borderColor+ " : " +borderWidth) ;
thisContext.strokeRect(0, 0 , x-borderWidth, y-borderWidth) ;
}
//Add BACKGROUND color
thisContext.fillStyle = bgFillColor ;
thisContext.fillRect(0,0,x,y);
在这里我们可以看到您正在查询 borderWith
,如果它不是零,请画一个边框。所以在这一点上你肯定有一个边界。问题从下一段代码开始:
thisContext.fillRect(0,0,x,y);
这基本上会用当前的填充样式清除整个 canvas。您通常需要将其作为第一个绘图操作。例如
thisContext.globalAlpha = 1.0;
thisContext.fillStyle = bgFillColor;
thisContext.fillRect(0,0,x,y);
if (borderWidth != 0) {
thisContext.strokeStyle = borderColor ;
thisContext.lineWidth = borderWidth ;
console.log(borderColor+ " : " +borderWidth) ;
thisContext.strokeRect(0, 0 , x-borderWidth, y-borderWidth);
}
#2 边框宽度影响文字笔画
在此代码块中,我们可以看到文本的笔画由名为 lineWidth
的变量确定。
case "stroke":
thisContext.lineWidth = lineWidth ;
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
问题是:您没有那个名称的变量,所以它使用 ID 为 lineWidth 的 html <input>
元素,returns 废话和 canvas 将采用 thisContext.lineWidth
的最后一个值,即边框的粗细。
只需添加一个
var lineWidth = document.getElementById("lineWidth").value;
在 buildBanner()
函数的开头。