搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
你好赵伟
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
美女与修狗儿【 InsCode Stable Diffusion 美图活动一期】
2
Unity Shader零基础入门4:纹理贴图与法线贴图_纹理贴图和法线贴图
3
Python 强大的模板引擎库 Skeleton BootStrap_python 模板引擎
4
STM32基本外设超详细44000字教程_stm32外设
5
K8s安全一
6
大致聊聊ChatGPT的底层原理,实现方法
7
帕金森病患者脑电时空微状态分析_全局场功率
8
1.5Reflect 与 Proxy_proxy(array)
9
python librosa显示音乐频谱_librosa 频谱
10
es6笔记····数组的扩展_es6三个点的语法
当前位置:
article
> 正文
wpf inkcanvas customink 毛笔效果_wpf inkcanvas 笔锋
作者:你好赵伟 | 2024-03-05 13:33:30
赞
踩
wpf inkcanvas 笔锋
联系QQ:715705486 18662431387
用wpf来做毛笔书写效果,需要自定义inkcanvas,基本效果可以,就是连续画很长的笔触时会有卡顿现象。解决方法,做一个判断,当笔触超过一定长度则停止。
核心代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input;
using System.Windows.Ink;
using System.Windows.Media.Imaging;
namespace WpfApplication1
{
class CustomRenderingInkCanvas:InkCanvas
{
CustomDynamicRenderer customRenderer = new CustomDynamicRenderer();
public CustomRenderingInkCanvas()
: base()
{
// Use the custom dynamic renderer on the
// custom InkCanvas.
this.DynamicRenderer = customRenderer;
}
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
{
// Remove the original stroke and add a custom stroke.
this.Strokes.Remove(e.Stroke);
CustomStroke customStroke = new CustomStroke(e.Stroke.StylusPoints);
this.Strokes.Add(customStroke);
// Pass the custom stroke to base class' OnStrokeCollected method.
InkCanvasStrokeCollectedEventArgs args =
new InkCanvasStrokeCollectedEventArgs(customStroke);
base.OnStrokeCollected(args);
}
}
// A class for rendering custom strokes
class CustomStroke : Stroke
{
Brush brush;
Pen pen;
public CustomStroke(StylusPointCollection stylusPoints)
: base(stylusPoints)
{
// Create the Brush and Pen used for drawing.
brush = new LinearGradientBrush(Colors.Red, Colors.Blue, 10d);
pen = new Pen(brush, 2d);
}
protected override void DrawCore(DrawingContext drawingContext,
DrawingAttributes drawingAttributes)
{
ImageSource img = new BitmapImage(new Uri(@"1.png", UriKind.RelativeOrAbsolute));
//前一个点的绘制。
Point prevPoint = new Point(double.NegativeInfinity,
double.NegativeInfinity);
int w = 10 + 15; //输出时笔刷的实际大小
Point pt = new Point(0, 0);
Vector v = new Vector(); //前一个点与当前点的距离
var subtractY = 0d; //当前点处前一点的Y偏移
var subtractX = 0d; //当前点处前一点的X偏移
var pointWidth = 10;
double x = 0, y = 0;
for (int i = 0; i < this.StylusPoints.Count; i++)
{
pt = (Point)this.StylusPoints[i];
v = Point.Subtract(prevPoint, pt);
// Debug.WriteLine("X " + pt.X + "\t" + pt.Y);
subtractY = (pt.Y - prevPoint.Y) / v.Length; //设置stylusPoints两个点之间需要填充的XY偏移
subtractX = (pt.X - prevPoint.X) / v.Length;
if (w - v.Length < 10) //控制笔刷大小
{
pointWidth = 10;
}
else
{
pointWidth = w - Convert.ToInt32(v.Length); //在两个点距离越大的时候,笔刷所展示的大小越小
}
for (double j = 0; j < v.Length; j = j + 1d) //填充stylusPoints两个点之间
{
x = 0; y = 0;
if (prevPoint.X == double.NegativeInfinity || prevPoint.Y == double.NegativeInfinity || double.PositiveInfinity == prevPoint.X || double.PositiveInfinity == prevPoint.Y)
{
y = pt.Y;
x = pt.X;
}
else
{
y = prevPoint.Y + subtractY;
x = prevPoint.X + subtractX;
}
drawingContext.DrawImage(img, new Rect(x - pointWidth / 2, y - pointWidth / 2, pointWidth, pointWidth)); //在当前点画笔刷图片
prevPoint = new Point(x, y);
if (double.IsNegativeInfinity(v.Length) || double.IsPositiveInfinity(v.Length))
{ break; }
}
}
// this.StylusPoints = null;
Allocate memory to store the previous point to draw from.
//Point prevPoint = new Point(double.NegativeInfinity,
// double.NegativeInfinity);
Draw linear gradient ellipses between
all the StylusPoints in the Stroke.
//for (int i = 0; i < this.StylusPoints.Count; i++)
//{
// Point pt = (Point)this.StylusPoints[i];
// Vector v = Point.Subtract(prevPoint, pt);
// // Only draw if we are at least 4 units away
// // from the end of the last ellipse. Otherwise,
// // we're just redrawing and wasting cycles.
// if (v.Length > 4)
// {
// // Set the thickness of the stroke
// // based on how hard the user pressed.
// double radius = this.StylusPoints[i].PressureFactor * 10d;
// drawingContext.DrawEllipse(brush, pen, pt, radius, radius);
// prevPoint = pt;
// }
//}
}
}
class CustomDynamicRenderer : DynamicRenderer
{
[ThreadStatic]
static private Brush brush = null;
[ThreadStatic]
static private Pen pen = null;
private Point prevPoint;
protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
// Allocate memory to store the previous point to draw from.
prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
base.OnStylusDown(rawStylusInput);
}
protected override void OnDraw(DrawingContext drawingContext,
StylusPointCollection stylusPoints,
Geometry geometry, Brush fillBrush)
{
ImageSource img = new BitmapImage(new Uri(@"1.png",UriKind.RelativeOrAbsolute));
//前一个点的绘制。
Point prevPoint = new Point(double.NegativeInfinity,
double.NegativeInfinity);
int w = 10 + 15; //输出时笔刷的实际大小
Point pt = new Point(0, 0);
Vector v = new Vector(); //前一个点与当前点的距离
var subtractY = 0d; //当前点处前一点的Y偏移
var subtractX = 0d; //当前点处前一点的X偏移
var pointWidth = 10;
double x = 0, y = 0;
for (int i = 0; i < stylusPoints.Count; i++)
{
pt = (Point)stylusPoints[i];
v = Point.Subtract(prevPoint, pt);
// Debug.WriteLine("X " + pt.X + "\t" + pt.Y);
subtractY = (pt.Y - prevPoint.Y) / v.Length; //设置stylusPoints两个点之间需要填充的XY偏移
subtractX = (pt.X - prevPoint.X) / v.Length;
if (w - v.Length < 10) //控制笔刷大小
{
pointWidth = 10;
}
else
{
pointWidth = w - Convert.ToInt32(v.Length); //在两个点距离越大的时候,笔刷所展示的大小越小
}
for (double j = 0; j < v.Length; j = j + 1d) //填充stylusPoints两个点之间
{
x = 0; y = 0;
if (prevPoint.X == double.NegativeInfinity || prevPoint.Y == double.NegativeInfinity || double.PositiveInfinity == prevPoint.X || double.PositiveInfinity == prevPoint.Y)
{
y = pt.Y;
x = pt.X;
}
else
{
y = prevPoint.Y + subtractY;
x = prevPoint.X + subtractX;
}
drawingContext.DrawImage(img, new Rect(x - pointWidth / 2, y - pointWidth / 2, pointWidth, pointWidth)); //在当前点画笔刷图片
prevPoint = new Point(x, y);
if (double.IsNegativeInfinity(v.Length) || double.IsPositiveInfinity(v.Length))
{ break; }
}
}
stylusPoints = null;
Create a new Brush, if necessary.
//if (brush == null)
//{
// brush = new LinearGradientBrush(Colors.Red, Colors.Blue, 20d);
//}
Create a new Pen, if necessary.
//if (pen == null)
//{
// pen = new Pen(brush, 2d);
//}
Draw linear gradient ellipses between
all the StylusPoints that have come in.
//for (int i = 0; i < stylusPoints.Count; i++)
//{
// Point pt = (Point)stylusPoints[i];
// Vector v = Point.Subtract(prevPoint, pt);
// // Only draw if we are at least 4 units away
// // from the end of the last ellipse. Otherwise,
// // we're just redrawing and wasting cycles.
// if (v.Length > 4)
// {
// // Set the thickness of the stroke based
// // on how hard the user pressed.
// double radius = stylusPoints[i].PressureFactor * 10d;
// drawingContext.DrawEllipse(brush, pen, pt, radius, radius);
// prevPoint = pt;
// }
//}
}
}
}
作者:yz qq:715705486
效果图如下:
声明:
本文内容由网友自发贡献,转载请注明出处:
【wpsshop】
推荐阅读
article
ACL
简介...
rule 5 deny丨permit source丨destination 192.168.1.0 0 规则编号 5(步...
赞
踩
article
软件工程
毕设
40
个高质量
SSM
毕设
项目
分享【源码+论文】_
软件工程
毕业设计
项目
...
管理员:首页、个人中心、病人管理、病例采集管理、预约管理、医生管理、上传核酸检测报告管理、上传行动轨迹管理、分类管理、病...
赞
踩
article
[转]
Linux
日志
管理详解_/
kunming
.
cyberpolice
.
cn
...
Linux
日志
管理详解from: http://
kunming
.
cyberpolice
.
cn
/aqjs/20001.ht...
赞
踩
article
软件工程
毕业设计
选题
100
例(一)...
软件工程
毕业设计
选题
文章目录 前言 题目1 : 基于SSM...
赞
踩
article
vim
实用指南
(
二)
:
查找
(
1
)——简单
查找
_
vim
查找
...
一、正向
查找
命令
:
/string 如要
查找
的是include,则在normal模式,先按/键,然后再输入
:
inc...
赞
踩
article
【
后
端的
讲解
】...
后
端开发包含许多编程语言的选项,如Java、C#, Python、Ruby、Node.js等。
后
端在软件开发领域通常是指...
赞
踩
article
机器
视觉
是指用
计算机
实现什么
的
视觉
功能
,
机器
视觉
是什么?主要
功能
可以
应用
到哪里?......
机器
视觉
:智能制造
的
“眼睛”。根据美国自动成像协会(AIA)
的
定义,
机器
视觉
是一种
应用
于工业和非工业领域
的
硬件和软件组合...
赞
踩
article
华为OD机试真题B卷
Java
实现【
停车场
车辆统计】,附详细解题思路_特定
大小
的
停车场
,
数组
car...
本专栏包含了最新最全
的
2023年华为OD机试真题,有详细
的
分析和
Java
解答。车辆
大小
不一,小车占一个车位(长度
1
),货...
赞
踩
article
海外
购物商城
源码
带
即时通讯
IM
源码
...
在
海外
购物商城中,
即时通讯
IM
源码
可以为用户提供更便捷、高效的沟通方式,帮助解决跨国交易中的语言和文化差异问题。总之,即...
赞
踩
article
JavaFx
实现
TableView
数据
全选
/取消
全选
功能
_
javafx
tableview
全选
...
最近做了一个桌面应用,使用到
TableView
显示查询到的设备信息,设备比较多,一个个勾选不方便,使用人员建议增加
全选
功...
赞
踩
article
js下载文件_
document
.
body
.
removechild
notfinderror
...
H5中a链接新增下载属性export const downloadFile = (blobFile, fileName)...
赞
踩
article
肖臻公开课(八)——
比特
币
中的
挖
矿_
比特
币
挖
到
区块
...
在本节中,肖老师首先回顾了一下节点的定义,然后讲了讲
挖
矿的现有的趋势。more。_
比特
币
挖
到
区块
比特
币
挖
到
区块
...
赞
踩
article
【
Python
】
表白
代码...
# -*- coding:utf-8 -*-import turtleimport time # 画爱心的顶部def L...
赞
踩
article
华为
Ensp
,
基本
ACL
,
高级
ACL
,
三层
ACL
,
二层
ACL
,
命名
ACL
配置大全_
华为
acl
编号
...
案例1
华为
基本
ACL
列表
编号
为2000~2999
,
高级3000~3999
,
二层4000~4999
,
用户自定义5000~5...
赞
踩
article
【转】
水文
模型
相关
_
gldas
水文
模型
...
水文
模型
_
gldas
水文
模型
gldas
水文
模型
这里主要记录几个...
赞
踩
article
数字赋能、
医疗
智变——
群晖
备份
存储
方案
,守护
医疗
数据
“生命线”_
hyper
backup
暂停...
备份
作为
数据
安全保护的唯一有效手段。只有进行了
数据
备份
,才能够在意外发生时快速恢复系统和
数据
,将损失降低到最小。所以为了...
赞
踩
article
[
转
]
Java
程序员
们
最常犯的
10
个
错误...
1.将数组
转
化为列表将数组
转
化为一
个
列表时,
程序员
们
经常这样做:List
list = Arrays.a...
赞
踩
article
Python
json
文件
常用操作_
python
json
操作...
Python
Json
文件
处理的四种常用方法_
python
json
操作
python
json
操作 ...
赞
踩
article
【
Linux
取经路】基础开发工具——
g
cc
/
g
++
篇_
linux
g
++
...
本文介绍了
g
cc
和
g
++
的一些常用指令,同时介绍了动态库和静态库的工作原理,以及它们的优缺点对比,帮助大家更好的理解编译...
赞
踩
article
JavaFx
用户界面控件3——
TableView
_
javafx
tableview
...
javaFx
TableView
_
javafx
tableview
javafx
tableview
...
赞
踩
相关标签
网络
运维
安全
java
linux
sun
login
authentication
unix
服务器
vim
查找
后端
机器视觉是指用计算机实现什么的视觉功能
算法
开发语言
海外通讯源码
通讯IM源码
javascript
区块链
学习
华为
网络协议
网络安全