`

FoxBPM 系列之-SVG输出浅析

阅读更多

为什么添加SVG支持?

       

       可伸缩矢量图形 (Scalable Vector Graphics)简称SVG,相对于普通的PNG图形文件,SVG格式有更好的展示效果,可以明显增加用户的体验。FoxBPM流程引擎同时支持PNG和SVG两种格式的输出。开发者可以根据用户需求动态的抉择。针对BPM产品SVG本身有着更多的优势:首先SVG本质就是一个XML,其对应的字符串可以直接在支持SVG的浏览器中展示,所以相对普通的图形文件SVG可以更加容易的输出到前端浏览器,在网络带宽不足的情况下这个优势就更加明显; 其次既然SVG本身是一个XML,那么我们就可以在前端像操作其他的DOM模型一样操作SVG,从而我们在浏览器前端也可以动态的改变流程图内容,从而添加更多功能(比如流程实例的运行轨迹,运行状态等)。

 

 主要知识点和难点:

        主要知识点包括:采用JAXB实现XML 和POJO之间的映射,VO的克隆,三次贝塞尔曲线的控制点计算,线条拐点的中心点计算等等。相关知识点核心代码如下所示:

 

VO对象克隆方法:

 /**
	 * DefsVO克隆 
	 * @param DefsVO 原对象
	 * @return clone之后的对象
	 */
	public final static GVO cloneGVO(GVO gVo) {
		return (GVO) clone(gVo);
	} 
	public final static DefsVO cloneDefsVO(DefsVO defsVo) {
		return (DefsVO) clone(defsVo);
	} 
 /**
	 * SvgVO模板对象需要多次引用,所以要克隆,避免产生问题 
	 * @param SvgVO  原对象
	 * @return clone之后的对象
	 */
	public final static SvgVO cloneSVGVo(SvgVO svgVo) {
		return (SvgVO) clone(svgVo);
	}        
 /**
	 * 克隆对象 
	 * @param object 原对象
	 * @return 目标对象
	 */
	public final static Object clone(Object object) {
		ByteArrayOutputStream bos = null;
		ObjectOutputStream oos = null;
		ObjectInputStream ois = null;
		Object cloneObject = null;
		try {
			bos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bos);
			oos.writeObject(object);
			ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
			cloneObject = ois.readObject();
		} catch (Exception e) {
			throw new FoxBPMException("SVG对象G节点克隆出现问题", e);
		} finally {
			try {
				if (bos != null) {
					bos.close();
				}
				if (oos != null) {
					oos.close();
				}
				if (ois != null) {
					ois.close();
				}
			} catch (Exception e) {
				throw new FoxBPMException("克隆之后关闭对象流时出现问题", e);
			}
		}

		return cloneObject;
	}

 

 

   JAXB映射方法(templateName是bpmn2.0官网提供的SVG模板名称):

 /**
	 * 第一次需要从svg文档加载
	 * 
	 * @param templateName
	 */
	private void init(String templateName) {
		try {
			JAXBContext context = JAXBContext.newInstance(SvgVO.class);
			Unmarshaller unMarshaller = context.createUnmarshaller();
			SAXParserFactory factory = SAXParserFactory.newInstance();
			// 解析的时候忽略SVG命名空间,否则会出错
			factory.setNamespaceAware(true);
			XMLReader reader = factory.newSAXParser().getXMLReader();
			String sourcePath = new StringBuffer(BPMN_PATH).append(FILE_SPERATOR)
					.append(templateName).toString();
			Source source = new SAXSource(reader, new InputSource(
					ReflectUtil.getResourceAsStream(sourcePath)));
			VONode object = (VONode) unMarshaller.unmarshal(source);
                        //将模板VO对象加入系统缓存
			this.svgTemplets.put(templateName, object);
		} catch (Exception e) {
			throw new FoxBPMException("template svg file load exception", e);
		} finally {
		}

	}
 /**
	 * 操作之后的SVG转化成String字符串 
	 * @param svgVo 容器对象
	 * @return SVG字符串
	 */
	public final static String createSVGString(VONode svgVo) {
		try {
			JAXBContext context = JAXBContext.newInstance(SvgVO.class);
			Marshaller marshal = context.createMarshaller();
			marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			StringWriter writer = new StringWriter();

			marshal.marshal(svgVo, writer);
			return writer.toString();
		} catch (Exception e) {
			throw new FoxBPMException("svg object convert to String exception", e);
		}
	}

 

 

    三次贝塞尔曲线的控制点以及线条中心点计算方法:

/**
 * Copyright 1996-2014 FoxBPM ORG.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @author MAENLIANG
 */
package org.foxbpm.engine.impl.diagramview.svg;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 坐标工具类 
 * @author MAENLIANG
 * @date 2014-06-19
 * 
 */
public final class PointUtils {
	/**
	 * X、Y允许的最大偏移量,超过最大偏移量需要设置文本相对线条的中心位置,如果小于这个         * 值则不需要设置
	 */
	private static final float X_Y_LOCATION_MAXSHIFT = 100F;
	// TODO后续改善成动态规划算法
	/**
	 * 默认圆角的大小,暂时分三个梯度
	 */
	private final static float SEQUENCE_ROUNDCONTROL_FLAG = 15.0f;
	private final static float SEQUENCE_ROUNDCONTROL_MIN_FLAG = 3.0f;
	private final static float NONE_SCALE = 1.0f;
	
	/**
	 * 计算三次贝塞尔曲线的起始点,控制点以及终点 
	 * @param start
	 * @param center
	 * @param end
	 * @return 起始点 控制点 终点坐标数组
	 */
	public final static Point[] caclBeralPoints(Point start, Point center, Point end) {
		float lengthStartHerizon = 0.0f;
		float lengthStartVertical = 0.0f;
		float lengthStartCenter = 0.0f;
		float lengthEndHerizon = 0.0f;
		float lengthEndVertical = 0.0f;
		float lengthEndCenter = 0.0f;
		
		lengthStartHerizon = Math.abs(start.getX() - center.getX());
		lengthStartVertical = Math.abs(start.getY() - center.getY());
		lengthStartCenter = (float) Math.sqrt(lengthStartHerizon * lengthStartHerizon
		        + lengthStartVertical * lengthStartVertical);
		lengthEndHerizon = Math.abs(end.getX() - center.getX());
		lengthEndVertical = Math.abs(end.getY() - center.getY());
		lengthEndCenter = (float) Math.sqrt(lengthEndHerizon * lengthEndHerizon + lengthEndVertical
		        * lengthEndVertical);
		
		float scale = SEQUENCE_ROUNDCONTROL_FLAG;
		if (lengthEndCenter <= SEQUENCE_ROUNDCONTROL_FLAG
		        || lengthStartCenter <= SEQUENCE_ROUNDCONTROL_FLAG) {
			if (lengthEndCenter <= SEQUENCE_ROUNDCONTROL_MIN_FLAG
			        || lengthStartCenter <= SEQUENCE_ROUNDCONTROL_MIN_FLAG) {
				scale = NONE_SCALE;
			} else {
				scale = SEQUENCE_ROUNDCONTROL_MIN_FLAG;
			}
			
		}
		float controlScale = scale / 3;
		Point[] points = new Point[4];
		points[0] = caclBeralControlPoint(start, center, scale, lengthStartHerizon, lengthStartVertical, lengthStartCenter);
		points[1] = caclBeralControlPoint(start, center, controlScale, lengthStartHerizon, lengthStartVertical, lengthStartCenter);
		points[2] = caclBeralControlPoint(end, center, controlScale, lengthEndHerizon, lengthEndVertical, lengthEndCenter);
		points[3] = caclBeralControlPoint(end, center, scale, lengthEndHerizon, lengthEndVertical, lengthEndCenter);
		return points;
	}
	
	/**
	 * 计算三次贝塞尔曲线控制点
	 * 
	 * @param startEndPoint
	 * @param center
	 * @return
	 */
	private final static Point caclBeralControlPoint(Point startEndPoint, Point center,
	    float scale, float lengthHerizon, float lengthVertical, float lengthCenter) {
		float startX = 0.0f;
		float startY = 0.0f;
		
		if (startEndPoint.getX() > center.getX()) {
			startX = ((scale * lengthHerizon) / lengthCenter) + center.getX();
		} else {
			startX = (((lengthCenter - scale) * lengthHerizon) / lengthCenter)
			        + startEndPoint.getX();
		}
		if (startEndPoint.getY() > center.getY()) {
			startY = ((scale * lengthVertical) / lengthCenter) + center.getY();
		} else {
			startY = (((lengthCenter - scale) * lengthVertical) / lengthCenter)
			        + startEndPoint.getY();
		}
		
		Point resultPoint = new Point(Math.round(startX), Math.round(startY));
		return resultPoint;
		
	}
	
	/**
	 * 计算中心点位置,包括复杂情况,和简单情况
	 * 
	 * @param pointList
	 * @return
	 */
	public final static Point caclDetailCenterPoint(List<Point> pointList) {
		Float[][] xyArrays = getXYLocationArray(pointList);
		Float[] xArrays = xyArrays[0];
		Float[] yArrays = xyArrays[1];
		float xShift = calCariance(xArrays);
		float yShift = calCariance(yArrays);
		// 如果偏差过大就计算中心点
		if (xShift > X_Y_LOCATION_MAXSHIFT && yShift < X_Y_LOCATION_MAXSHIFT) {
			// X坐标拐点幅度大,Y不大,计算线条X中心位置,Y取平均值
			return caclXCenter(xArrays, yArrays);
			
		} else if (yShift > X_Y_LOCATION_MAXSHIFT && xShift < X_Y_LOCATION_MAXSHIFT) {
			// Y坐标拐点幅度大,X不大,计算线条Y中心位置,X取平均值
			return caclYCenter(xArrays, yArrays);
			
		} else if (yShift > X_Y_LOCATION_MAXSHIFT && xShift > X_Y_LOCATION_MAXSHIFT) {
			// XY拐点幅度都比较大
			return caclCenterPoint(pointList);
		} 
		// 如果没有计算中心点
		return null; 
	}
	
	/**
	 * 勾股定理, 取线段长度
	 * 
	 * @param pointA
	 * @param pointB
	 * @return
	 */
	public final static float segmentLength(Point pointA, Point pointB) {
		double length = 0;
		float width = pointA.getX() - pointA.getX();
		float height = pointA.getY() - pointB.getY();
		double dWidth = (double) width;
		double dHeight = (double) height; 
		length = Math.sqrt(Math.pow(dWidth, 2) + Math.pow(dHeight, 2));
		return (float) length;
	}
	
	/**
	 * 统计所有线段的长度
	 * 
	 * @param pointList
	 * @return
	 */
	private final static List<Float> getSegmentsLength(List<Point> pointList) {
		List<Float> segList = new ArrayList<Float>();
		
		float segLen = 0f;
		int size = pointList.size();
		size = size - 1;
		Point pointA = null;
		Point pointB = null;
		for (int i = 0; i < size; i++) {
			pointA = pointList.get(i);
			pointB = pointList.get(i + 1);
			
			segLen = segmentLength(pointA, pointB);
			segList.add(segLen);
		}
		
		return segList;
	}
	
	/**
	 * 计算所有x坐标值或者y坐标值的方差,判断是否需要重新设置所有拐点的中心点
	 * 
	 * @param array
	 * @return
	 */
	public final static Float calCariance(Float[] array) {
		int arrayLength = array.length;
		Float ave = 0.0F;
		for (int i = 0; i < arrayLength; i++) {
			ave += array[i];
		}
		ave /= arrayLength;
		Float sum = 0.0F;
		for (int i = 0; i < arrayLength; i++) {
			sum += (array[i] - ave) * (array[i] - ave);
		}
		sum = sum / arrayLength;
		return sum;
	}
	
	/**
	 * 获取所有点的XY坐标
	 * 
	 * @param pointList
	 * @return
	 */
	private final static Float[][] getXYLocationArray(List<Point> pointList) {
		int pointListsize = pointList.size();
		Float[][] xyLocationArray = new Float[2][pointListsize];
		Iterator<Point> iterator = pointList.iterator();
		for (int i = 0; i < pointListsize; i++) {
			Point next = iterator.next();
			xyLocationArray[0][i] = next.getX();
			xyLocationArray[1][i] = next.getY();
		}
		return xyLocationArray;
	}
	
	/**
	 * 计算线条在X方向上的中心位置
	 * 
	 * @param xArrays
	 * @param yArrays
	 * @return
	 */
	public final static Point caclXCenter(Float[] xArrays, Float[] yArrays) {
		Arrays.sort(xArrays);
		int length = yArrays.length;
		Float xCenter = xArrays[0] + (xArrays[xArrays.length - 1] - xArrays[0]) / 2;
		Float tempV = 0.0f;
		for (int i = 0; i < length; i++) {
			tempV += yArrays[i];
		}
		Float y = tempV / length;
		return new Point(xCenter, y);
	}
	
	/**
	 * 计算线条在y方向上的中心位置
	 * 
	 * @param xArrays
	 * @param yArrays
	 * @return
	 */
	public final static Point caclYCenter(Float[] xArrays, Float[] yArrays) {
		Arrays.sort(yArrays);
		Float yCenter = yArrays[0] + (yArrays[yArrays.length - 1] - yArrays[0]) / 2;
		Float tempV = 0.0f;
		int length = xArrays.length;
		for (int i = 0; i < length; i++) {
			tempV += xArrays[i];
		}
		Float x = tempV / length;
		return new Point(yCenter, x);
	}
	
	/**
	 * 计算中心点
	 * 
	 * @param svgLine
	 * @return
	 */
	public final static Point caclCenterPoint(List<Point> pointList) {
		List<Float> segList = PointUtils.getSegmentsLength(pointList);
		float totalLength = 0f;
		for (float seg : segList) {
			totalLength += seg;
		}
		
		float centerLen = totalLength / 2;
		
		int keySegIndex = 0;
		
		float keySeg = 0f;
		float tempLen = 0f;
		for (float seg : segList) {
			keySeg = seg;
			keySegIndex++;
			if ((tempLen + keySeg) > centerLen) {
				break;
			} else {
				tempLen += keySeg;
			}
			
		}
		
		float lastLen = centerLen - tempLen;
		
		Point startPoint = pointList.get(keySegIndex - 1);
		Point endPoint = pointList.get(keySegIndex); 
		float scale = lastLen / keySeg; 
		float x = startPoint.getX() + (endPoint.getX() - startPoint.getX()) * scale;
		float y = startPoint.getY() + (endPoint.getY() - startPoint.getY()) * scale;
		Point point = new Point(x, y);
		return point;
	}
}

 

模块结构详细说明:

结构如下图所示:


         1、模块构建基于工厂和创建者设计模式,独立于SVG,对其他矢量标记语言扩展友好。

 

         2、FoxBpmnViewBuilder为VO属性构建的上层接口,当创建新的元素时,可以针对元素的特性进行实现。流程引擎后期的维护和功能扩展也主要是针对该接口的实现。

 

         3、AbstractFlowElementVOFactory也是VO属性构建的上层抽象类,负责VO对象的获取、过滤、以及根据特定元素选择特定Builder构建VO属性。

 

         4、svg包模块是针对FoxBpmnViewBuilder和AbstractFlowElementVOFactory的svg实现,包括svg工厂、svg 构建者、svg VO模型、svg工具类。

 

SVG构建详细说明:

        1、流程引擎启动初始化的时候,将BPMN2.0官网提供的所有SVG模版(其模版以单个组件的形式提供)初始化,采用映射工具JAXB 将模版转化成VO对象并且加入缓存。

 

    VO定义如下代码所示: 

/**
 * Copyright 1996-2014 FoxBPM ORG.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @author MAENLIANG
 */
package org.foxbpm.engine.impl.diagramview.vo;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;

/**
 * SVG对象的超类,包括 节点SVG对象,连接线SVG对象
 * 
 * @author MAENLIANG
 * @date 2014-06-10
 * 
 */
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class VONode implements Serializable { 
	private static final long serialVersionUID = -817550474604039751L;
	/**
	 * ID Name 用于标记流程元素ID用于 流程图的前端操作
	 */
	@XmlAttribute(name = "id")
	protected String id;
	@XmlAttribute(name = "name")
	protected String name; 
	@XmlAttribute(name = "style")
	protected String style; 
	@XmlAttribute(name = "fill")
	protected String fill; 
	@XmlAttribute(name = "stroke")
	protected String stroke; 
	@XmlAttribute(name = "stroke-width")
	protected Float strokeWidth;
	@XmlAttribute(name = "stroke-linecap")
	protected String strokeLinecap;
	@XmlAttribute(name = "stroke-linejoin")
	protected String strokeLinejoin;
	@XmlAttribute(name = "width")
	protected Float width;
	@XmlAttribute(name = "height")
	protected Float height;
	@XmlAttribute(name = "x")
	protected Float x;
	@XmlAttribute(name = "y")
	protected Float y;
	@XmlValue
	protected String elementValue;

	public String getElementValue() {
		return elementValue;
	} 
	public void setElementValue(String elementValue) {
		this.elementValue = elementValue;
	} 
	public Float getX() {
		return x;
	} 
	public void setX(Float x) {
		this.x = x;
	} 
	public Float getY() {
		return y;
	} 
	public void setY(Float y) {
		this.y = y;
	} 
	public String getStyle() {
		return style;
	} 
	public void setStyle(String style) {
		this.style = style;
	} 
	public String getFill() {
		return fill;
	} 
	public void setFill(String fill) {
		this.fill = fill;
	} 
	public String getStroke() {
		return stroke;
	} 
	public void setStroke(String stroke) {
		this.stroke = stroke;
	} 
	public float getStrokeWidth() {
		return strokeWidth;
	} 
	public void setStrokeWidth(float strokeWidth) {
		this.strokeWidth = strokeWidth;
	} 
	public float getWidth() {
		return width;
	} 
	public void setWidth(float width) {
		this.width = width;
	} 
	public float getHeight() {
		return height;
	} 
	public void setHeight(float height) {
		this.height = height;
	} 
	public String getId() {
		return id;
	} 
	public void setId(String id) {
		this.id = id;
	} 
	public String getName() {
		return name;
	} 
	public void setName(String name) {
		this.name = name;
	} 
	public String getStrokeLinecap() {
		return strokeLinecap;
	} 
	public void setStrokeLinecap(String strokeLinecap) {
		this.strokeLinecap = strokeLinecap;
	} 
	public String getStrokeLinejoin() {
		return strokeLinejoin;
	} 
	public void setStrokeLinejoin(String strokeLinejoin) {
		this.strokeLinejoin = strokeLinejoin;
	}
}
 

 

           2、SVG模版相对独立,当创建时流程引擎提供包含所有流程元素定义的流程定义对象,流程元素包括 节点、线条、泳道、部件,其中节点包括活动任务、事件、网关。SVG创建者首先创建一个VO集合,然后根据流程元素从缓存中获取每个元素对应的自己的VO对象,获取VO 对象之后根据每个元素的式样属性来设置其VO属性,需要实现的接口为FoxBpmnViewBuilder,VO对象属性设置好之后添加到VO集合中。

 

FoxBpmnViewBuilder代码如下:

/**
 * Copyright 1996-2014 FoxBPM ORG.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @author MAENLIANG
 */
package org.foxbpm.engine.impl.diagramview.builder;

import java.util.List;

import org.foxbpm.engine.impl.diagramview.svg.Point;

/**
 * 流程图形信息构造接口
 * 
 * @author MAENLIANG
 * @date 2014-06-10
 */
public interface FoxBpmnViewBuilder {
	public static final String SEQUENCE_STROKEWIDTH_DEFAULT = "2";
	public static final String COLOR_FLAG = "#";
	public static final String STROKE_DEFAULT = "black";
	public static final String STROKEWIDTH_DEFAULT = "1";
	public static final int LINEARGRADIENT_INDEX = 0;
	public static final String COMMA = ",";
	public static final String BACK_GROUND_PREFIX = "url(#";
	public static final String BACK_GROUND_SUFFIX = ") #";
	
	public static final String BRACKET_SUFFIX = ")";
	public static final String TRANSLANT_PREFIX = "translate(";
	public static final String ARIAL = "arial";
	
	

	/**
	 * 设置节点信息
	 */
	public void setWayPoints(List<Point> pointList); 
	public void setWidth(float width); 
	public void setHeight(float height); 
	public void setXAndY(float x, float y); 
	public void setStroke(String stroke); 
	public void setStrokeWidth(float strokeWidth); 
	public void setFill(String fill); 
	public void setID(String id); 
	public void setName(String name); 
	public void setStyle(String style);

	/**
	 * 设置文本信息
	 */
	public void setText(String text); 
	public void setTextFont(String font); 
	public void setTextStrokeWidth(float textStrokeWidth); 
	public void setTextX(float textX); 
	public void setTextY(float textY); 
	public void setTextFontSize(String textFontSize); 
	public void setTextStroke(String textStroke); 
	public void setTextFill(String textFill); 

        /**
         * 设置子类型
         */
	public void setTypeStroke(String stroke); 
	public void setTypeStrokeWidth(float strokeWidth); 
	public void setTypeFill(String fill); 
	public void setTypeStyle(String style);

	/**
	 * 泳道负责重写该方法 setTextLocationByHerizonFlag
	 */
	public void setTextLocationByHerizonFlag(boolean herizonFlag);
}

 

 

          3、所有元素的VO对象设置好之后,再根据流程定义提供的基本信息创建SVG模版对象,然后将所有的VO对象克隆并且添加到模版对象,然后将模版对象用JAXB 工具转化成最终的SVG XML文档

 

   流程定义对象所包含的元素如下所以:

	List<KernelFlowNodeImpl> flowNodes = new ArrayList<KernelFlowNodeImpl>(); 
	Map<String, KernelSequenceFlowImpl> sequenceFlows = new HashMap<String, KernelSeque        nceFlowImpl>(); 
	List<KernelLaneSet> laneSets = new ArrayList<KernelLaneSet>();
	List<KernelArtifact> artifacts = new ArrayList<KernelArtifact>();
 

 

foxbpm流程引擎构建SVG示意图如下:



 
 

 

  • 大小: 32.4 KB
  • 大小: 62.7 KB
  • 大小: 15.5 KB
分享到:
评论

相关推荐

    如何使用vite-svg-loader

    "使用 Vite-SVG-Loader 实现 SVG 图像的轻量级引入" 在现代 Web 开发中,使用 SVG 图像已经成为一个非常常见的需求,特别是在 Vue 应用程序中。然而,引入 SVG 图像经常会遇到一些问题,例如图像大小问题、浏览器...

    jaxb-svg11-1.0.2-API文档-中文版.zip

    赠送jar包:jaxb-svg11-1.0.2.jar; 赠送原API文档:jaxb-svg11-1.0.2-javadoc.jar; 赠送源代码:jaxb-svg11-1.0.2-sources.jar; 赠送Maven依赖信息文件:jaxb-svg11-1.0.2.pom; 包含翻译后的API文档:jaxb-svg11...

    save-ps-to-svg 1.0.zip

    《Photoshop到SVG转换脚本详解——save-ps-to-svg 1.0》 在数字艺术与设计领域,Photoshop(简称PS)是一款广泛使用的图像处理软件,而SVG(Scalable Vector Graphics)则是一种基于XML的矢量图形格式,尤其适用于...

    save-ps-to-svg1.0.jsx.zip

    SVG是一种基于XML的图像格式,它允许无限的缩放而不会失去清晰度或质量,这使得SVG在网页设计、移动应用以及需要高分辨率输出的项目中非常流行。与像素基础的图像格式(如JPEG或PNG)不同,SVG是基于路径的,这意味...

    save-ps-to-svg1.0.rar

    使用这样的脚本,用户可以通过调用Photoshop的API来控制软件进行文件操作,如打开PS文件,解析其内容,然后输出为SVG格式。 使用脚本转换PS文件到SVG的优势在于可以批量处理多个文件,自定义转换参数,以及在特定...

    save-ps-to-svg1.0.jsx转换工具.zip

    SVG路径是由一系列坐标点和指令组成的,可以精确地表示出复杂的几何形状。在Photoshop中,形状图层包含填充、描边、透明度等属性,这些属性在转换为SVG时都会得到保留。因此,使用save-ps-to-svg1.0.jsx脚本,你可以...

    save-ps-to-svg1.0.jsx 让Ps支持svg格式

    总的来说,"save-ps-to-svg1.0.jsx" 是Photoshop用户的实用工具,它使得在没有第三方插件的情况下也能方便地导出SVG文件,极大地拓宽了Photoshop的输出格式范围,对于需要SVG格式的设计师而言,这是一个非常有价值的...

    save-ps-to-svg1.0.zip 让PS支持导出SVG

    标题“save-ps-to-svg1.0.zip 让PS支持导出SVG”揭示了一个关于Adobe Photoshop(简称PS)的扩展功能,即添加了将形状图片转换为SVG(Scalable Vector Graphics)路径的能力。SVG是一种基于XML的矢量图像格式,具有...

    山武NX-SVG软件包

    山武NX-SVG软件包是山武NX-SVG网关设置与调试用的软件,可以做很方便的和其它通讯第三方通讯,省去PLC不少的通讯程序

    NN-SVG-master.zip

    NN-SVG-master.zip是一个压缩包,包含了用于绘制神经网络架构的SVG图像的工具。这个工具特别之处在于它支持三种不同的神经网络模型的图形表示:全连接神经网络(FCNN)、LeNet以及AlexNet。这些模型在深度学习领域...

    jaxb-svg11-1.0.2-API文档-中英对照版.zip

    赠送jar包:jaxb-svg11-1.0.2.jar; 赠送原API文档:jaxb-svg11-1.0.2-javadoc.jar; 赠送源代码:jaxb-svg11-1.0.2-sources.jar; 赠送Maven依赖信息文件:jaxb-svg11-1.0.2.pom; 包含翻译后的API文档:jaxb-svg11...

    react-native-svg-uri, 在来自URL或者 static 文件的本地响应中,呈现SVG图像.zip

    react-native-svg-uri, 在来自URL或者 static 文件的本地响应中,呈现SVG图像 react-native-svg-uri从URL或者 static 文件中呈现来自React的SVG图像这是用 rn 0.33和 react-native-svg 4.3.1 ( 依赖于此库) react-...

    star-rating-svg _ jQuery星级评分插件

    **jQuery星级评分插件——star-rating-svg详解** 在网页设计中,用户反馈和评价系统是不可或缺的一部分,而星级评分则是最直观、最常见的表现形式。`star-rating-svg`是一款基于jQuery的星级评分插件,它利用SVG...

    save-ps-to-svg1.0.zip

    PhotoShop 将形状图片转化为 svg路径的脚本, 将形状文件转化导出为 SVG路径

    HTML5-SVG超人飞翔动画特效.rar

    HTML5-SVG超人飞翔动画特效.rar HTML5-SVG超人飞翔动画特效.rar HTML5-SVG超人飞翔动画特效.rar HTML5-SVG超人飞翔动画特效.rar HTML5-SVG超人飞翔动画特效.rar HTML5-SVG超人飞翔动画特效.rar HTML5-SVG超人飞翔...

    前端开源库-babel-plugin-inline-react-svg

    **前端开源库-babel-plugin-inline-react-svg** 在前端开发中,SVG(Scalable Vector Graphics)因其可伸缩性、良好的浏览器支持以及丰富的图形能力,常被用来创建图标和其他矢量图形。然而,将SVG引入React应用时...

    save-ps-to-svg1.0.jsx

    直接 PhotoShop 直接将形状文件转化导出为 SVG路径的脚本

    react-native-qrcode-svg:基于react-native-svg和node-qrcode的React Native QR码生成器

    讨论: : 产品特点轻松渲染QR码图像(可选)嵌入徽标安卓的iOS安装安装依赖包yarn add react-native-svg react-native-qrcode-svg 要么npm i -S react-native-svg react-native-qrcode-svg 如果您使用的是React ...

Global site tag (gtag.js) - Google Analytics