天道酬勤,学无止境

如何使画布文本可选?(How to Make Canvas Text Selectable?)

问题

任何建议都将受到高度赞赏。

回答1

文本选择具有许多视觉上的,一些非视觉上的组成部分。

首先,使文本成为可选文本,您必须保留一个数组,该数组包含文本的位置,文本的含义以及所使用的字体。 您将通过Canvas函数measureText使用此信息。

通过使用measureText和文本字符串,您可以确定单击图像时光标应落在哪个字母上。

ctx.fillText("My String", 100, 100);
textWidth = ctx.measureText("My String").width;

您仍然必须从“字体”属性解析字体高度,因为该属性当前未包含在文本指标中。 画布文本默认情况下与基线对齐。

有了这些信息,您现在有了一个边界框,可以对其进行检查。 如果光标位于边界框内,那么您现在将承担推论一下故意选择了哪个字母的不幸任务。 光标的起始位置。 这可能涉及多次调用measureText。

到那时,您知道光标应该移到哪里了。 当然,您需要将文本字符串作为文本字符串存储在变量中。

一旦定义了范围的起点和终点,就必须绘制一个选择指示器。 这可以在新的图层(第二个画布元素)中完成,也可以使用XOR合成模式绘制一个矩形来完成。 也可以通过简单地清除和重绘填充矩形上方的文本来完成此操作。

总而言之,在Canvas中进行文本选择,文本编辑非常费力,并且重新使用已经编写的组件是明智的,Bespin是一个很好的例子。

如果遇到其他公共示例,我将编辑我的帖子。 我相信Bespin使用基于网格的选择方法,可能需要等宽字体。 字体渲染的连字,字距调整,双向性和其他高级功能需要额外的编程; 这是一个复杂的问题。

回答2

TextInput控件很复杂

首先,我要说我不是文本控件方面的专家,但是到现在,我相信这无关紧要,因为我可以帮助您安全地出入树林。 这些事物本质上是复杂的,需要对事物如何运作有足够的直觉和知识。 但是,您可以在此处检查在senpai-js/senpai-stage存储库中运行的代码。

我们应该预先定义一些内容:

  • 文本可以是任何有效的unicode字符。 您可以使用以下正则表达式进行解析: /^.$/u
  • 您需要跟踪三种不同类型的文本编辑模式: InsertSelectionBasic (我在库中使用SelectionState枚举,并在舞台上检查insertMode属性)
  • 您应该随时进行健全性检查,否则您将有未定义和意外的行为
  • 大多数人期望文本输入可以按宽度调整大小,因此,如果计划使用纹理,请确保对文本框的内部使用模式
  • 除非确保文本输入控件不会旋转,否则鼠标/触摸点碰撞检测很复杂
  • 当文本在水平方向上大于文本框时,文本应滚动。 我们将其称为textScroll ,它始终是负数

现在,我将遍历每个函数以描述其行为,以准确描述文本框控件应如何工作。

碰撞(broadPhase和narrowPhase)

碰撞检测是一个怪物。 标准化鼠标和触摸事件之间的点移动是本文中未涉及的复杂野兽。 一旦处理了点事件,就必须对矩形执行某种常规的碰撞检测。 这意味着要进行AABB碰撞。 如果文本框精灵本身已旋转,则必须“取消旋转”该点本身。 但是,如果鼠标/触摸点已经位于文本框上方,则我们绕过此检查。 这是因为一旦开始选择文本,就希望此函数始终返回true 。 然后,我们移到窄阶段冲突,该冲突实际上会检查“未变换”的鼠标/触摸点是否在文本框的填充范围内。 如果是,或者文本框处于活动状态,我们将在此处返回一个真实值。

一旦知道鼠标/触摸点在文本框的范围内,就可以将画布的CSS更改为cursor: text; 视觉上。

pointCollision

当我们在文本框上按下鼠标按钮时,我们需要计算将插入符号移动到的位置。 插入符号的范围为0text.length含)。 请注意,这并不完全正确,因为unicode字符的长度可以为2 。 您必须跟踪数组中添加到文本的每个字符,以断言您不是在测量错误的Unicode字符。 计算目标索引意味着循环遍历当前文本的每个字符,并将其附加到临时字符串,每次进行测量,直到所测量的宽度大于当前textScroll +所测量的textWidth为止。

一旦我们确定该点已落在文本框顶部并设置了起点,就可以启动“选择”模式。 拖动点应将选择从起始插入索引移动到新计算出的结束索引。 这是双向的。

此处显示了一个示例。

keyPresses

Web按键的解决方案是检查KeyEvent上的key属性。 尽管每个人都说了很多,但是可以通过对上述unicode regex进行测试来测试该文本属性。 如果匹配,则可能是实际上已在键盘上按下过该键。 这不考虑用于复制和粘贴的组合键,例如ctrl + cctrl + v 。 这些功能微不足道,由读者自己决定如何实现这些功能。

少数几个例外是箭头键:“ ArrowLeft”,“ ArrowRight”等。这些键实际上会修改控件的状态并更改其功能。 重要的是要记住,关键事件只能由当前focused控件处理。 这意味着您应该检查并确保控件在文本输入过程中处于聚焦状态。 当然,这发生在比我在库中编写的代码更高的级别上,所以这是微不足道的。

下一个需要解决的问题是每个字符输入应如何修改控件的状态。 keyDown方法可识别selectionState并根据其状态调用不同的函数。 这不是经过优化的伪代码,而是用于清楚起见,非常适合我们描述行为的目的。

选择时按下

  • 普通按键将替换所选文本的内容
  • selectionStart拼接出来,然后将新键插入文本数组
  • 如果按下“删除”或“退格”键,则剪接所选内容,并将选择模式返回到“ Normal或“ Caret
  • 如果按下“向左”或“向右”键,则分别将光标移动到开始或结束处,然后将选择模式返回到“正常”,除非按下Shift键
  • 如果按下Shift键,那么我们实际上想进一步扩展选择范围
    • 选择开始将始终在caretIndex处,并且我们实际上使用此组合键将选择结束点向左或向右移动
    • 如果选择端返回到插入符号索引,我们将selectionState再次返回到Normal
  • “ home”和“ end”键的工作方式相同,只是将插入号分别移至0text.length索引
    • 还请注意,按住Shift键可再次从caretIndex扩展选择范围

正常模式(插入符号模式)下的按键

  • 在插入符号模式下,我们不会替换任何文本,只需在当前位置插入新字符
  • 使用splice方法插入与Unicode正则表达式匹配的keydown
  • 插入文本后,将插入符号移到右侧(检查并确保不超过文本长度)
  • 退格键删除caretIndex - 1的索引之前的一个字符caretIndex - 1
  • Delete删除在caretIndex处的索引后的一个字符
  • 按住Shift键的同时,文本选择适用于左右键
  • 当不按shift键时,左右分别将插入符号向左和向右移动
  • Home键将caretIndex设置为0
  • 结束键将caretIndex设置为text.length

插入模式下的keyDown

  • 在插入模式下,我们在caretIndex处替换当前选择的字符
  • 使用splice方法插入与Unicode正则表达式匹配的keydown
  • 插入文本后,将插入符号移到右侧(检查并确保没有超过文本长度)
  • 退格键在当前选择之前删除字符
  • 删除删除当前选择的字符
  • 箭头键正常工作并在正常模式下描述
  • 归位键和结束键按预期方式工作,并在正常模式下进行了描述

每隔一帧更新文本框

  • 如果文本框已聚焦,则应开始闪烁插入符号,以使用户知道他们正在编辑文本框中的文本
  • 将插入符向左或向右时Caret模式,你应该重新启动闪光灯机构,使之准确显示他们在哪里,每次移动尖号
  • 每30帧或半秒刷新一次插入符号
  • 通过使用ctx.measureText到插入符号索引来测量插入符号沿文本的距离,方法是将文本切成插入符号的位置,除非模式为Selection
  • 在选择模式Selection测量文本沿文本的距离仍然有用,因为我们始终希望文本选择的结尾对用户可见
  • 考虑到当前的textScroll,请确保插入符始终在文本框的可见范围内可见

渲染文本框

  • 首先保存上下文ctx.save() (基本画布)
  • 如果您没有绘制带有路径的文本框,请分别在第一层上绘制文本框的左帽,绘制中间图案和右帽
  • 使用由填充和文本框的大小定义的路径来裁剪正方形,以防止文本渗出
  • 转换为x textScroll值,该值应为负数
  • 转换为y midline值,该值应垂直位于文本框的中间
  • 设置字体属性
  • 将文本基线设置为middle并通过在文本数组上调用text.join("")来填充文本
  • 如果有选择或插入模式,请确保在所选文本后面绘制一个“蓝色”正方形,并反转所选文本的字体颜色(这是不平凡的,留给读者作为练习)
回答3

由于canvas标签的性质,无法选择在canvas元素中绘制的文本。 但是有一些解决方法,例如用于typefaceJS的解决方法。

另一种解决方案是添加具有定位div元素的文本,而不是使用strokeText或fillText。

回答4

如果需要可选文本,则只需创建一个div或其他内容,然后将其放置在希望显示文本的画布上会容易得多。

canvas没有内置的用于选择文本的机制,因此您必须推出自己的文本呈现和选择代码-正确起来可能非常棘手。

回答5

您可能会从Bespin那里得到一些想法。

他们使用画布,文字选择,滚动条,光标闪烁等在javascript中实现了文本编辑器

源代码

回答6

我建议使用EaselJS库,您可以将每个字母作为孩子添加,甚至可以向该对象添加鼠标事件,这是一个了不起的库,请检查一下!

回答7

FabricJS现在可以与canvas元素外部的对象进行交互-例如,此演示显示了一个按钮,该按钮链接到canvas元素中加载的图像。

通过挂接任何move事件,获取元素的边界框并重新放置HTML元素,可以在其他库(如Raphael)中使用相同的方法。

回答8

画布只是一个绘图表面。 您渲染,结果是像素。 因此,您需要以某种数据结构跟踪您渲染到画布上的所有文本的位置,该结构将在鼠标事件期间进行处理。

回答9

一个简单的答案是:要么使用HTML要么使用SVG而不是canvas。 除非您确实需要画布提供的底层控制级别。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 确定HTML5画布中字符串的宽度(Determine width of string in HTML5 canvas)
    问题 我正在图像(模因生成器)顶部的HTML5画布中绘制文本。 我想计算一个字体大小,以便该字符串跨越画布的整个宽度。 因此,基本上,JavaScript中是否有一种方法可以确定对于给定宽度的某种字体的某些字符串我应该使用哪种字体大小? 回答1 fillText()方法有一个可选的第四个参数,它是呈现字符串的最大宽度。 MDN的文档说... maxWidth 可选的; 绘制的最大宽度。 如果指定了该字符串,并且计算出的字符串的宽度大于此宽度,则将字体调整为使用水平方向更紧凑的字体(如果可用,或者可以通过水平缩放当前字体来合成合理可读的字体)或更小字体。 但是,在撰写本文时,跨浏览器还不支持该参数,这导致第二种解决方案使用measureText()来确定字符串的尺寸而不渲染它。 var width = ctx.measureText(text).width; 这是我可能会做的... var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); // Font sizes must be in descending order. You may need to use `sort()` // if you can't guarantee this, e.g. user input. var
  • HTML5画布中的居中(比例字体)文本(Center (proportional font) text in an HTML5 canvas)
    问题 我希望能够在可以计算的矩形区域内将单行文本居中。 我期望在画布上的2D几何图形中做的一件事就是将宽度未知的东西居中。 作为一种解决方法,我听说可以在HTML容器中创建文本,然后调用jQuery的width()函数,但是我不是正确地处理了文档主体中的瞬时添加吗? 宽度为0 如果我只有一行文字,比填满屏幕大部分宽度的文字短得多,如何知道以我知道的字体大小在画布上的宽度? 回答1 如果您不需要文本的宽度,而只想居中,则可以 canvas_context.textBaseline = 'middle'; canvas_context.textAlign = "center"; 哪个应该使文本在垂直和水平居中。 回答2 您可以使用measureText来做到这一点 var canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d") canvas.width = 400; canvas.height = 200; ctx.fillStyle = "#003300"; ctx.font = '20px sans-serif'; var textString = "Hello look at me!!!", textWidth = ctx.measureText(textString ).width
  • 画布文本渲染(模糊)(Canvas text rendering (blurry))
    问题 我知道这个问题已经被问过很多次了,但是我尝试了几乎所有可以在网上找到的东西,但是无论我尝试了什么(以及使用什么组合),仍然无法在画布上正确呈现文本。 对于模糊的线条和形状问题,只需将+ 0.5px添加到坐标即可解决该问题:但是,此解决方案似乎不适用于文本渲染。 注意:我从不使用CSS来设置画布的宽度和高度(只尝试过一次以检查在HTML和CSS中设置大小属性是否会改变任何内容)。 同样的问题似乎与浏览器无关。 我试过了 : 用HTML创建画布,然后用javascript而不是html创建画布在HTML元素中设置宽度和高度,然后使用JS,然后同时使用HTML和JS 使用所有可能的组合将0.5px添加到文本坐标更改字体系列和字体大小更改字体大小单位(px,pt,em) 使用不同的浏览器打开文件以检查是否有任何更改使用canvas.getContext('2d', {alpha:false})禁用Alpha通道canvas.getContext('2d', {alpha:false})这只是使我的大多数图层消失而没有解决问题 在此处查看canvas和html字体渲染之间的比较:https://jsfiddle.net/balleronde/1e9a5xbf/ 甚至有可能使画布中的文本像dom元素中的文本一样呈现吗? 任何意见或建议将不胜感激 回答1 画布上的DOM质量文本。 仔细看看
  • 有什么办法可以使WPF文本块成为可选的?(Any way to make a WPF textblock selectable?)
    问题 如何允许TextBlock的文本是可选的? 我试图通过使用只读的TextBox来显示文本,使其看起来像文本块,从而使其正常工作,但是在我的情况下,这是不起作用的,因为TextBox没有内联。 换句话说,如何使其成为可选择的? 回答1 而是使用具有这些设置的TextBox使其只读并看起来像TextBlock控件。 <TextBox Background="Transparent" BorderThickness="0" Text="{Binding Text, Mode=OneWay}" IsReadOnly="True" TextWrapping="Wrap" /> 回答2 这里的所有答案都只是使用TextBox或尝试手动实现文本选择,这会导致性能不佳或非本地行为( TextBox插入记号闪烁,手动实现中不支持键盘等)。 经过数小时的研究和阅读WPF源代码,我发现了一种为TextBlock控件(或实际上是任何其他控件)启用本机WPF文本选择的方法。 围绕文本选择的大多数功能是在System.Windows.Documents.TextEditor系统类中实现的。 要为控件启用文本选择,您需要做两件事: 一次调用TextEditor.RegisterCommandHandlers()以注册类事件处理程序为类的每个实例创建一个TextEditor实例,然后将System
  • 使用Javascript获取画布中的最大字体大小(Use Javascript to get Maximum font size in canvas)
    问题 我正在绘制需要在整个可用屏幕上(100%的宽度和高度)的画布。 我像这样使用javascript设置画布的宽度和高度 var w = window.innerWidth; var h = window.innerHeight; var canvas = document.getElementById("myCanvas"); canvas.width = w; canvas.height = h; 设置画布后,我需要在其中绘制一些文本,以获取最大可用字体大小。 请帮助我找到如何显示最大字体大小的文本的方法。 文本可以包含单个字符(大写和小写)或字符串,也可以包含数字。 我需要用JavaScript而不是jquery来做。 感谢您的帮助。 回答1 挑战 由于canvas的measureText当前不支持测量高度(上升+下降),因此我们需要做一些DOM技巧来获取行高。 由于字体(或字体)的实际高度不一定(很少)与字体大小相对应,因此我们需要一种更准确的度量方式。 解决方案 小提琴演示 结果将是垂直对齐的文本,该文本始终适合画布的宽度。 该解决方案将自动获得字体的最佳大小。 第一个功能是包装measureText以支持高度。 如果文本指标的新实现不可用,请使用DOM: function textMetrics(ctx, txt) { var tm = ctx.measureText
  • 将文本分成页面并单独显示(HTML5)(Split text into pages and present separately (HTML5))
    问题 假设我们有一个长文本,例如Romeo&Juliet,我们想在一个简单的电子阅读器中显示它(没有动画,只有页面和自定义字体大小)。 有什么方法可以做到这一点? 到目前为止,我想出了什么: 使用css3列,可以将整个文本加载到内存中,使其样式化,使单个列占据整个页面的大小。 这样做很难控制,并且需要将整个文本加载到内存中。 使用css3区域(在任何主要浏览器中均不支持)将构成与先前解决方案相同的基本概念,主要区别在于控制起来不会那么困难(因为每个“列”都是一个自包含的元素)。 在画布上绘制文本可以使您确切地知道文本的结尾,从而在此基础上绘制下一页。 优点之一是您只需要将所有文本加载到当前页面即可(仍然很差,但是更好)。 缺点是无法与文本进行交互(例如选择文本)。 将每个单词放置在一个元素内,并为每个元素赋予唯一的ID(或在javascript中保留逻辑引用),然后使用document.elementFromPoint查找页面上最后一个元素(单词),并从下开始显示下一页这个词。 尽管这是唯一对我而言似乎实际可行的方法,但这样做所产生的开销却是巨大的。 然而,这些似乎都不是可以接受的(第一个没有给予足够的控制甚至无法使其正常工作,第二个还不被支持,第三个是困难且没有文本选择,第四个给出了可笑的开销),所以任何好的方法我尚未考虑过解决上述方法的一个或多个缺点的方法(是的
  • 如何在HTML5 canvas元素上编写文本?(How can I write text on a HTML5 canvas element?)
    问题 是否可以在HTML5 canvas上编写文本? 回答1 var canvas = document.getElementById("my-canvas"); var context = canvas.getContext("2d"); context.fillStyle = "blue"; context.font = "bold 16px Arial"; context.fillText("Zibri", (canvas.width / 2) - 17, (canvas.height / 2) + 8); #my-canvas { background: #FF0; } <canvas id="my-canvas" width="200" height="120"></canvas> 回答2 在画布上绘制文本 标记: <canvas id="myCanvas" width="300" height="150"></canvas> 脚本(有几个不同的选项): <script> var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.font = 'italic 18px Arial'; ctx.textAlign = 'center'; ctx
  • 在HTML5画布上绘制旋转文本(Drawing rotated text on a HTML5 canvas)
    问题 我正在开发的Web应用程序的一部分要求我创建条形图以显示各种信息。 我认为,如果用户的浏览器具有功能,则可以使用HTML5 canvas元素绘制它们。 我没有为我的图形绘制线条和条形的问题,但是当涉及到标注轴,条形或线的标签时,我遇到了麻烦。 如何将旋转的文本绘制到画布元素上,使其与要标记的项目对齐? 几个示例包括: 逆时针旋转文本90度以标记y轴逆时针旋转文本90度以在垂直条形图上标记条形图任意旋转文本以标记折线图上的线 任何指针将不胜感激。 回答1 就像其他人提到的那样,您可能想看看重用现有的图形解决方案,但是旋转文本并不是太困难。 (对我而言)有些令人困惑的一点是,您旋转了整个上下文然后在其上进行绘制: ctx.rotate(Math.PI*2/(i*6)); 角度以弧度为单位。 该代码取自该示例,我相信该示例是为MDC画布教程的转换部分制作的。 请参阅下面的答案以获取更完整的解决方案。 回答2 发布此信息是为了帮助有类似问题的其他人。 我通过五步方法解决了这个问题-保存上下文,转换上下文,旋转上下文,绘制文本,然后将上下文还原为其保存状态。 我认为平移和转换为上下文是操纵覆盖在画布上的坐标网格。 默认情况下,原点(0,0)从画布的左上角开始。 X从左到右增加,Y从上到下增加。 如果您用左手的食指和拇指做一个“ L”,并在您的拇指向下的情况下将其按住在您的面前
  • 如何修复HTML5画布中的模糊文本?(How do I fix blurry text in my HTML5 canvas?)
    问题 我总的n00b HTML5和我有工作canvas渲染形状,颜色和文字。 在我的应用程序中,我有一个视图适配器,可以动态创建画布,并用内容填充它。 效果非常好,除了我的文本非常模糊/模糊/拉伸。 我还看到了许多其他文章,说明为什么在CSS定义宽度和高度会导致此问题,但我在javascript都定义了这些内容。 相关代码(查看小提琴): var width = 500;//FIXME:size.w; var height = 500;//FIXME:size.h; var canvas = document.createElement("canvas"); //canvas.className="singleUserCanvas"; canvas.width=width; canvas.height=height; canvas.border = "3px solid #999999"; canvas.bgcolor = "#999999"; canvas.margin = "(0, 2%, 0, 2%)"; var context = canvas.getContext("2d"); ////////////////// //// SHAPES //// ////////////////// var left = 0; //draw zone 1 rect context
  • 画布上的Android Center文本(Android Center text on canvas)
    问题 我正在尝试使用下面的代码显示文本。 问题是文本没有水平居中。 当我设置drawText的坐标时,它将在此位置设置文本的底部。 我希望绘制文本,以便文本也水平居中。 这是进一步显示我的问题的图片: @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); //canvas.drawRGB(2, 2, 200); Paint textPaint = new Paint(); textPaint.setARGB(200, 254, 0, 0); textPaint.setTextAlign(Align.CENTER); textPaint.setTypeface(font); textPaint.setTextSize(300); canvas.drawText("Hello", canvas.getWidth()/2, canvas.getHeight()/2 , textPaint); } 回答1 请尝试以下操作: Paint textPaint = new Paint(); textPaint.setTextAlign(Paint.Align.CENTER); int xPos = (canvas.getWidth() /
  • 如何找到HTML画布上文本的高度?(How can you find the height of text on an HTML canvas?)
    问题 规范中有一个context.measureText(text)函数,该函数将告诉您打印该文本需要多少宽度,但是我找不到找到高度的方法。 我知道它是基于字体的,但是我不知道将字体字符串转换为文本高度。 回答1 更新-作为此工作的示例,我在Carota编辑器中使用了此技术。 继ellisbben的回答之后,这是一个增强版本,可从基线获得上升和下降,即与Win32的GetTextMetric API返回的tmAscent和tmDescent相同。 如果您想用不同字体/大小的跨度进行文字包装的文本,则需要这样做。 上面的图像是在Safari中的画布上生成的,红色是指示画布绘制文本的最上面一行,绿色是基线,蓝色是底部(所以红色到蓝色是完整高度)。 使用jQuery简洁: var getTextHeight = function(font) { var text = $('<span>Hg</span>').css({ fontFamily: font }); var block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>'); var div = $('<div></div>'); div.append(text, block); var body = $('body'); body
  • 如何使tkinter画布动态调整为窗口宽度?(How to get tkinter canvas to dynamically resize to window width?)
    问题 我需要在tkinter中获得一个画布,以将其宽度设置为窗口的宽度,然后在用户使窗口变小/变大时动态调整画布的大小。 有什么办法(轻松)吗? 回答1 我以为我会添加一些额外的代码来扩展@fredtantini的答案,因为它不涉及如何更新在Canvas上绘制的小部件的形状。 为此,您需要使用scale方法并标记所有小部件。 下面是一个完整的示例。 from Tkinter import * # a subclass of Canvas for dealing with resizing of windows class ResizingCanvas(Canvas): def __init__(self,parent,**kwargs): Canvas.__init__(self,parent,**kwargs) self.bind("<Configure>", self.on_resize) self.height = self.winfo_reqheight() self.width = self.winfo_reqwidth() def on_resize(self,event): # determine the ratio of old width/height to new width/height wscale = float(event.width)/self
  • HTML5画布与SVG与div(HTML5 Canvas vs. SVG vs. div)
    问题 即时创建元素并能够四处移动的最佳方法是什么? 例如,假设我要创建一个矩形,圆形和多边形,然后选择这些对象并四处移动。 我了解HTML5提供了三个使之成为可能的元素:svg,canvas和div。 对于我想做什么,这些元素中的哪一个将提供最佳性能? 为了比较这些方法,我正在考虑创建三个视觉上相同的网页,每个网页中都有页眉,页脚,小部件和文本内容。 第一页中的小部件将完全使用canvas元素创建,第二页将完全使用svg元素创建,而第三页将使用纯div元素HTML和CSS创建。 回答1 简短的答案: SVG对您来说将更加容易,因为已经内置了选择和移动它的功能。SVG对象是DOM对象,因此它们具有“ click”处理程序等。 DIV可以,但是笨重,并且在大量情况下具有糟糕的性能加载。 Canvas具有最佳的性能,但是您必须自己实现托管状态(对象选择等)的所有概念,或者使用库。 长答案: HTML5 Canvas只是位图的绘图表面。 您设置进行绘制(用颜色和线条粗细说),绘制该东西,然后Canvas不知道该东西:它不知道它在哪里或刚刚绘制的是什么,它是只是像素。 如果要绘制矩形并使其移动或可以选择,则必须从头开始编写所有代码,包括要记住已绘制矩形的代码。 另一方面,SVG必须维护对其呈现的每个对象的引用。 您创建的每个SVG / VML元素都是DOM中的真实元素。 默认情况下
  • iOS 7中的UITextView链接检测(UITextView link detection in iOS 7)
    问题 我有一个UITextView ,它是通过Interface Builder管理的。 作为数据检测,我检查了“链接”。 在iOS 6中,一切正常,链接突出显示并且可以单击。 但是,在iOS 7中,所有链接都只是纯文本。 未选中可编辑和可选复选框。 可能令人担心的是, UITextView是容器视图的子视图,该视图又位于UIScrollView 。 回答1 似乎在iOS 7中,只有在UITextView是可选的情况下,链接检测才起作用。 因此,使我的UITextView不可选择停止了链接检测的工作。 我也在iOS 6中对此进行了测试,并且可以确认在iOS 6中,即使无法选择UITextView ,链接检测也可以正常工作。 回答2 我今天在电话号码检测方面遇到了一些问题。 在我将文本设置为其他内容之后,UITextView似乎会保留旧的电话号码并突出显示文本。 我发现,如果在将文本设置为新字符串之前先设置setText:nil,它将重置textview,并且电话号码将像往常一样突出显示。 我想知道这是否是iOS 7.0中的UITextView的某种错误 无论哪种方式,这确实对我有用。 回答3 当iOS7首次问世时,这困扰了我,我在此线程中找到了答案(在设置实际值之前将UITextView的text属性设置为nil可以解决问题)。 然后突然,问题
  • 如何在画布的边界内绘制geom_text图(How to make geom_text plot within the canvas's bounds)
    问题 使用geom_text标记散点图的外围点。 根据定义,这些点往往靠近画布边缘:通常至少有一个单词与画布边缘重叠,从而使它无用。 显然,在以下情况下,可以使用+ xlim(c(1.5, 4.5))手动解决此问题: # test df <- data.frame(word = c("bicycle", "tricycle", "quadricycle"), n.wheels = c(2,3,4), utility = c(10,6,7)) ggplot(data=df, aes(x=n.wheels, y=utility, label=word)) + geom_text() + xlim(c(1.5, 4.5)) 不过这并不理想,因为 它不是自动化的,因此如果要生产许多样地,则会减慢该过程这是不准确的,这意味着单词的边缘和画布的边缘之间的距离在每种情况下都不相等。 搜索此问题不会发现任何解决方案,并且Hadley Wickham似乎对ggplot2的帮助页面中的标签减少了一半感到满意(我知道Hadley,它们只是一个示例;) 回答1 ggplot 2.0.0引入了针对geom_text() hjust和vjust新选项,可能有助于剪切,尤其是"inward" 。 我们可以做: ggplot(data=df, aes(x=n.wheels, y=utility, label
  • 在fabricJS中如何使用transformMatrix转换点?(How does transforming points with a transformMatrix work in fabricJS?)
    问题 我试图将点(通过fabric.Circle )放置在fabric.Polygon的角上。 多边形可以由用户移动,缩放或旋转。 但是,每次修改后,我都希望具有多边形的新坐标以将我的圆放置在那里。 在深入研究该主题时,我发现了转换矩阵的出色解释。 我认为这是我想要实现的完美解决方案。 但是,正如您在小提琴中看到的那样,我的点总是偏离多边形。 由于我对几何变换等并不坚定。我希望有人能找到我的错误并告诉我我所缺少的东西:)谢谢。 var canvas = new fabric.Canvas("c", {selection: false}); var polygon = new fabric.Polygon([ new fabric.Point(200, 50), new fabric.Point(250, 150), new fabric.Point(150, 150) ]); polygon.on("modified", function () { var matrix = this.calcTransformMatrix(); var transformedPoints = this.get("points").map(function(p){ return fabric.util.transformPoint(p, matrix); }); var circles =
  • 从文本html画布中提取路径(extract path from text html canvas)
    问题 无论如何,是否有从html 5的文本字母中提取路径,然后沿该路径抓取(x,y)坐标,以便该字母可以由沿该字母路径的圆圈组成? 我想采用x,y坐标,并在其位置应用形状,以使其类似于“像素化”格式的文本字符串,并带有一些动画效果。 关于在画布上沿字符路径获取某种x,y坐标的任何建议都是很好的。 编辑:我本质上是试图自动生成坐标以执行类似于此的操作:http://www.html5canvastutorials.com/labs/html5-canvas-google-bouncing-balls/ 回答1 像素缩放 一种简单的方法是执行以下操作: 使用小字体,使用纯色绘制文本迭代所有像素。 任何alpha = 255的像素,存储到数组中,但x和y随直径缩放 现在,您有了代表文本的粗略的“球”阵列,并且可以进行动画处理。 在字母间距方面,它不是超级准确,但应该针对给定的目的进行操作(您始终可以测量每个字母,并在分隔点处使用额外的增量值来增加x的末尾值)。 较大的字体可以提高质量,但也会产生更多的磅数。 与下面的演示中使用的通用字体不同的字体类型也可能有益于整体外观(实验!)。 您还可以调整Alpha阈值,以包括不完全固定但有影响力的像素。 最后,不同的浏览器以不同的方式呈现文本,因此您可能也需要牢记这一点(请参阅上文中有关测量每个字母以在它们之间添加额外空间的内容)。 演示版
  • 如何使生成的内容可选?(How can I make generated content selectable?)
    问题 我可以让CSS通过使用生成的内容来显示元素的ID,如下所示: <style> h2:hover:after { color: grey; content: "#" attr(id); float: right; font-size: smaller; font-weight: normal; } </style> <h2 id="my-id">My ID</h2> <p>Pellentesque habitant morbi tristique senectus et netus et.</p> 如何使生成的内容(“#my-id”)可选,以便用户突出显示和复制它? 回答1 您无法选择伪元素,因为它在DOM中不存在。 5.10伪元素和伪类伪元素或伪类都不会出现在文档源或文档树中。 回答2 伪元素不存在于DOM中。 因此,您无法选择它们。
  • Fabric.js-如何使用自定义属性在服务器上保存画布(Fabric.js - how to save canvas on server with custom attributes)
    问题 我希望能够将当前canvas的状态保存为服务器端数据库(可能作为JSON字符串),然后再使用loadFromJSON还原它。 通常,使用以下方法可以轻松实现此目的: var canvas = new fabric.Canvas(); function saveCanvas() { // convert canvas to a json string var json = JSON.stringify( canvas.toJSON() ); // save via xhr $.post('/save', { json : json }, function(resp){ // do whatever ... }, 'json'); } 进而 function loadCanvas(json) { // parse the data into the canvas canvas.loadFromJSON(json); // re-render the canvas canvas.renderAll(); // optional canvas.calculateOffset(); } 但是,我还使用内置的Object#set方法在要添加到画布上的结构对象上设置了一些自定义属性: // get some item from the canvas var item = canvas
  • 在画布上绘制多行文字(Draw multi-line text to Canvas)
    问题 一个希望很快的问题,但是我似乎找不到任何示例...我想通过Canvas将多行文本写到自定义View ,并且在onDraw()我有: ... String text = "This is\nmulti-line\ntext"; canvas.drawText(text, 100, 100, mTextPaint); ... 我希望这会导致换行,但我看到的是\n所在的隐秘字符。 任何指针表示赞赏。 保罗 回答1 不幸的是,Android不知道\n是什么。 您需要做的是去除\n ,然后偏移Y以使您的文本显示在下一行。 所以像这样: canvas.drawText("This is", 100, 100, mTextPaint); canvas.drawText("multi-line", 100, 150, mTextPaint); canvas.drawText("text", 100, 200, mTextPaint); 回答2 我发现了使用静态布局的另一种方法。 该代码在这里供任何人参考: TextPaint mTextPaint=new TextPaint(); StaticLayout mTextLayout = new StaticLayout(mText, mTextPaint, canvas.getWidth(), Alignment.ALIGN_NORMAL, 1