背景:
由于项目的需要,当用户在查看流程图时,当点击某个流程图片上的节点时,需要提示一些信息,这就需要获取各个节点的信息,此处获取id和name的值。
注意:这个并不是流程图的高亮,即当点击网点申请环节时,获取该节点的id和name,即B001和网点申请,点击部门申请时,获取B002和部门经理审批
解释说明: 博文来源:http://www.fhadmin.org/webnewsdetail1.html
1.下方说的x和y:
2.流程定义的key: 即为下方id的值
3.节点的id和name的值:
难点分析:
由 于activiti在部署时,如果没有流程图片,则activiti会自动生成一张图片,而我们项目中使用的是activiti modeler实现的在线画流程图,部署时没有图片,是由activiti自动生成。而activiti在生成图片时,会对图片做一个裁剪操作,所有最终 各个节点的坐标会比实际的要小。
(即:activiti自动生成的图片,会做一个裁剪操作,各个节点实际的x和y的值比xml文件中的要小)
而我们的难点在于,各个节点实际坐标的获取。如下图所示:
即我们实际上获取的坐标需要在减去一个minX和minY,得到的才是我们的各个节点实际的坐标。
步骤分析:
1.根据流程定义的key,重新生成流程图片,而不是获取流程图片。
2.还是根据流程定义的key,获取各个节点的信息。(此处需要注意的是各个节点实际的x和y的值的获取的方法)
3.在jsp页面上使用绝对定位,给点击的节点加上高亮。
步骤实现: 1.根据流程定义的key,重新生成流程图片,而不是获取流程图片。
此处重新生成图片的原因:
因为有些时候我们在部署流程时,将图片也部署进去了,此时使用的就是自己的图片,activiti不会进行图片的裁剪。因为我在下一步获取流程节点的信息时,对x和y的进行了特殊处理,因此此处需要重新生成 流程图片。
-
-
-
-
-
-
-
- @RequestMapping("/genericImageByWfKey")
- public void genericImageByWfKey(HttpServletRequest request, HttpServletResponse response, String wfKey) {
- Context.setProcessEngineConfiguration(processEngineConfiguration);
- RepositoryService repositoryService = this.processEngine.getRepositoryService();
- ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey(wfKey).latestVersion().singleResult();
- BpmnModel bm = repositoryService.getBpmnModel(pd.getId());
- "color: #ff6600;">InputStream is = ProcessDiagramGenerator.generatePngDiagram(bm);
- try {
- int size = is.available();
- byte data[] = new byte[size];
- is.read(data);
- response.setContentType("image/png");
- OutputStream os = response.getOutputStream();
- os.write(data);
- os.flush();
- os.close();
- } catch (IOException e) {
- log.error("读写流程图时出现异常!");
- }
- log.info("end....");
- }
2.还是根据流程定义的key,获取各个节点的信息。
获取各个节点的坐标之前,我们先看一下activiti中是如果获取到最小的x和y的,然后是如何裁剪图片的
2.1获取节点包括线的最小x和最小y :
跟踪acticiti的源码可以发现,最小x和y的获取(org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator.initProcessDiagramCanvas(BpmnModel))
- protected static ProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel) {
-
- double minX = Double.MAX_VALUE;
- double maxX = 0;
- double minY = Double.MAX_VALUE;
- double maxY = 0;
-
- for (Pool pool : bpmnModel.getPools()) {
- GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
- minX = graphicInfo.getX();
- maxX = graphicInfo.getX() + graphicInfo.getWidth();
- minY = graphicInfo.getY();
- maxY = graphicInfo.getY() + graphicInfo.getHeight();
- }
-
- List flowNodes = gatherAllFlowNodes(bpmnModel);
- for (FlowNode flowNode : flowNodes) {
-
- GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
-
-
- if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) {
- maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth();
- }
- if (flowNodeGraphicInfo.getX() < minX) {
- minX = flowNodeGraphicInfo.getX();
- }
-
- if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) {
- maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight();
- }
- if (flowNodeGraphicInfo.getY() < minY) {
- minY = flowNodeGraphicInfo.getY();
- }
-
- for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
- List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());
- for (GraphicInfo graphicInfo : graphicInfoList) {
-
- if (graphicInfo.getX() > maxX) {
- maxX = graphicInfo.getX();
- }
- if (graphicInfo.getX() < minX) {
- minX = graphicInfo.getX();
- }
-
- if (graphicInfo.getY() > maxY) {
- maxY = graphicInfo.getY();
- }
- if (graphicInfo.getY()< minY) {
- minY = graphicInfo.getY();
- }
- }
- }
- }
-
- int nrOfLanes = 0;
- for (Process process : bpmnModel.getProcesses()) {
- for (Lane l : process.getLanes()) {
-
- nrOfLanes++;
-
- GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId());
-
- if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) {
- maxX = graphicInfo.getX() + graphicInfo.getWidth();
- }
- if (graphicInfo.getX() < minX) {
- minX = graphicInfo.getX();
- }
-
- if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) {
- maxY = graphicInfo.getY() + graphicInfo.getHeight();
- }
- if (graphicInfo.getY() < minY) {
- minY = graphicInfo.getY();
- }
- }
- }
-
-
- if (flowNodes.size() == 0 && bpmnModel.getPools().size() == 0 && nrOfLanes == 0) {
-
- minX = 0;
- minY = 0;
- }
-
- return "color: #ff0000;">new ProcessDiagramCanvas((int) maxX + 10,(int) maxY + 10, (int) minX, (int) minY);
- }
2.2 图片的裁剪:
还是activiti的源码:(org.activiti.engine.impl.bpmn.diagram.ProcessDiagramCanvas.generateImage(String))
-
-
-
-
-
-
- public InputStream generateImage(String imageType) {
- if (closed) {
- throw new ActivitiException("ProcessDiagramGenerator already closed");
- }
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
-
- minX = (minX <= 5) ? 5 : minX;
- minY = (minY <= 5) ? 5 : minY;
- BufferedImage imageToSerialize = processDiagram;
- if (minX >= 0 && minY >= 0) {
- "font-size: 16px; color: #ff0000;">
- "color: #ff0000;">imageToSerialize = processDiagram.getSubimage(minX - 5, minY - 5, canvasWidth - minX + 5, canvasHeight - minY + 5);
- }
- ImageIO.write(imageToSerialize, imageType, out);
- } catch (IOException e) {
- throw new ActivitiException("Error while generating process image", e);
- } finally {
- IoUtil.closeSilently(out);
- }
- return new ByteArrayInputStream(out.toByteArray());
- }
2.3 我们自己的各个节点的信息获取
- @RequestMapping("/getProcessTrace")
- @ResponseBody
-
-
-
-
-
-
- public List
- List
- RepositoryService repositoryService = processEngine.getRepositoryService();
- ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey(wfKey).latestVersion().singleResult();
- ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(pd.getId());
- List activitiList = processDefinition.getActivities();
- InputStream xmlIs = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
- BpmnModel bm = new BpmnXMLConverter().convertToBpmnModel(new InputStreamSource(xmlIs), false, true);
-
- "color: #ff0000;">
- "color: #ff0000;">Class> clazz = Class.forName("org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator");
- Method method = clazz.getDeclaredMethod("initProcessDiagramCanvas", BpmnModel.class);
- method.setAccessible(true);
- ProcessDiagramCanvas pdc = (ProcessDiagramCanvas) method.invoke(clazz.newInstance(), bm);
-
- clazz = Class.forName("org.activiti.engine.impl.bpmn.diagram.ProcessDiagramCanvas");
- Field minXField = clazz.getDeclaredField("minX");
- Field minYField = clazz.getDeclaredField("minY");
- minXField.setAccessible(true);
- minYField.setAccessible(true);
- int minX = minXField.getInt(pdc);
- int minY = minYField.getInt(pdc);
-
-
- minX = minX > 0 ? minX - 5 : 0; "color: #ff0000;">
- minY = minY > 0 ? minY - 5 : 0;
- for (ActivityImpl activity : activitiList) {
- Map activityInfo = new HashMap();
- activityInfo.put("width", activity.getWidth());
- activityInfo.put("height", activity.getHeight());
- activityInfo.put("x", activity.getX() - minX);
- activityInfo.put("y", activity.getY() - minY);
- activityInfo.put("actId", activity.getId());
- "color: #ff0000;">activityInfo.put("name", activity.getProperty("name")); ActivityImpl 中没有getName方法,所以此处需要这样获取。
- activityInfos.add(activityInfo);
- }
- return activityInfos;
- }
3.在jsp页面上使用绝对定位,给点击的节点加上高亮。
-
-
- "Content-Type" content="text/html; charset=UTF-8">
- Insert title here
-
-
-
-
-
"main">
-
"flowImageAndRect">
-
-
-
-
"processKey" style="font-size: 52px;text-align: center;margin-bottom: 50px;">
-
-
-
-
"info" style="font-size: 52px;text-align: center;">
-
-
-
-
-
到此,已经完成了。