motivación:
Primero pensé en hacer un árbol binario porque necesitaba hacer un gráfico de estructura de la empresa. El enfoque anterior consistía en hacer un dibujo directamente utilizando un software de gráficos. Se ve muy bien, pero hay que pintar uno nuevo cada vez que hay cambios. Por otro lado, la visualización y el diseño de líneas en las páginas web son bastante limitados. La composición tipográfica y el posicionamiento basados en datos generados dinámicamente son muy difíciles y la estética no es satisfactoria. Después de varios intentos, decidí usar XML + XSL para operaciones de datos; usar VML para embellecer líneas y usar JAVASCRIPT para posicionar objetos.
Material:
El diagrama de árbol de estructura del volumen XML tiene 2 archivos: flow2.xml y flow2.xsl
Efecto:
Navegar aquí
explicar:
Idea de árbol binario (1)
<html xmlns:v="urn:schemas-microsoft-com:vml">
<ESTILO>
v:* { COMPORTAMIENTO: url(#default#VML) }
</ESTILO>
<v:id de grupo="grupo1" nombre="grupo1" tamaño de coordenada = "100,100">
…
</v:grupo>
Estos son los formatos básicos de VML, por lo que no los explicaré en detalle.
XML es una estructura de árbol cuando leemos cada dato, necesitamos
Se recorre el árbol de datos XML. Las operaciones recursivas son una de las ventajas de XSL.
También decidí usar XSL después de usar varios otros métodos para realizar operaciones transversales y fallé.
<Raíz de flujo>
<vcTitle>Árbol binario--diagrama de estructura</vcTitle>
<Author>Vuelo en vela</Author>
<Correo electrónico>[email protected]</Correo electrónico>
<Nodo de flujo>
<iProceso>1</iProceso>
<vcCourse>Primer nodo</vcCourse>
<iSiguienteSí>
<Nodo de flujo>
<iProceso>2</iProceso>
<vcCourse>Segundo nodo</vcCourse>
<iSiguienteSí>…</iSiguienteSí>
<iSiguienteNo>…</iSiguienteNo>
</FlowNode>
</iSiguienteSí>
<iNºSiguiente>
<Nodo de flujo>
<iProceso>3</iProceso>
<vcCourse>El tercer nodo</vcCourse>
<iSiguienteSí>…</iSiguienteSí>
<iSiguienteNo>…</iSiguienteNo>
</FlowNode>
</iNextNo>
</FlowNode>
</raíz de flujo>
La lógica es muy simple. Hay dos nodos secundarios (2, 3) bajo el nodo actual (1).
Simplemente coloque el nodo 2 y el nodo 3 en la parte inferior izquierda y derecha del nodo 1.
Aquí utilizo verde y rojo para las líneas de conexión de los nodos izquierdo y derecho respectivamente para una fácil visualización.
Hablamos anteriormente sobre la función recursiva de XSL. Para ver cada paso de visualización detallado con mayor claridad, solo necesita imitar el siguiente código y agregar una declaración de alerta.
<xsl:template match="FlowNode">
…
<lenguaje SCRIPT="JavaScript1.2">
…
alert('mostrar paso a paso');
…
</SCRIPT>
…
</xsl:plantilla>
Después de ver la cámara lenta de arriba, ¿puedes entender mis pensamientos?
Idea de árbol binario (2)
Mi idea es muy simple:
(1) Lea los datos del nodo actual y genere un nuevo objeto usando VML.
Asigne un valor inicial al objeto (como nombre, identificación, estilo, etc.)
(2) Utilice el control de secuencia de comandos para posicionar el objeto actual. (3) Agregue flechas y líneas entre el nodo actual y su nodo principal.
(4) Continúe buscando los nodos secundarios del nodo actual y realice un bucle hasta el final.
Es decir, se han atravesado todos los nodos y se ha generado el árbol.
<xsl:template match="FlowNode">
…
<xsl:aplicar-plantillas />
…
</xsl:plantilla>
<xsl:template match="iSiguienteSí">
<xsl:apply-templates select="./FlowNode" />
</xsl:template>
<xsl:template match="iNextNo">
<xsl:apply-templates select="./FlowNode" />
</xsl:plantilla>
Todo el proceso recursivo se completa con los tres módulos (plantillas) anteriores.
La primera plantilla llama a las dos plantillas siguientes cuando coincide con la plantilla de cada nodo secundario en el nodo actual, y las dos últimas plantillas llaman a la primera plantilla durante una ejecución específica, lo que equivale a una función recursiva.
gramática:
Para hacer coincidir las plantillas de cada nodo secundario en el nodo actual, use el formulario base del elemento <xsl:apply-templates />.
De lo contrario, el nodo coincidente está determinado por el valor de la expresión XPath en el parámetro de selección, como <xsl:apply-templates select="./FlowNode" />
Las funciones de (1) y (2) son devolver el valor de cadena de la expresión dada por el parámetro de selección.
Sus condiciones de búsqueda son las mismas, por lo que los valores devueltos también son los mismos.
Es sólo que sus formas de escritura son diferentes según las ocasiones en que se utilizan.
(1) <xsl:valor-de seleccionar="./iProcess/text()" />
(2) {./iProcess/text()}
Algunas variables se definen aquí y el posicionamiento del nodo se basa en estas variables para llamar a la fórmula de cálculo.
root_left //El margen izquierdo de la raíz = el ancho asignado de todas las hojas (y*10) + el ancho de todas las hojas (y*50) + el valor básico del margen izquierdo (10)
root_top //El margen superior de la raíz = el valor básico del margen superior (10)
objOval //El objeto actual es un objeto
objOval_iProcess //Valor del paso del objeto actual
objParentOval //El nodo padre del objeto actual es un objeto
objParentOval_iProcess //El valor del paso del nodo principal del objeto actual
objParent_name //El nombre del nodo padre del objeto actual
Leaf_left //El número de hojas izquierdas entre todos los nodos secundarios del objeto actual
Leaf_right //El número de hojas derechas entre todos los nodos secundarios del objeto actual
Leaf_sum //El número de hojas entre todos los nodos secundarios del objeto actual
Leaf: se refiere al nodo actual que no tiene nodos secundarios.
Fórmula de posicionamiento del nodo:
(1) El nodo actual es el nodo raíz
//La posición de la raíz.
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//La función de la función parseInt() es tomar el valor entero, si no, será NAN
// La función de la función isNaN () es determinar si el valor obtenido por parseInt es un número entero.
(2) El nodo actual es el nodo secundario izquierdo del nodo principal
1) Las condiciones para el juicio son: El nombre del nodo principal del objeto actual = 'iNextYes'
…
2) Si hay una hoja secundaria derecha, la fórmula es:
La izquierda del nodo actual = la izquierda del nodo padre - el ancho total de la hoja secundaria derecha del nodo actual - el ancho del nodo actual
3) Si no hay una hoja secundaria derecha, pero hay una hoja secundaria izquierda , la fórmula es:
La izquierda del nodo actual = la izquierda del nodo padre - el ancho total de la hoja secundaria izquierda del nodo actual
4) Si el nodo actual en sí es una hoja, la fórmula es:
La izquierda del nodo actual = la izquierda del nodo principal - el ancho del nodo actual...
(3) El nodo actual es el nodo secundario derecho del nodo principal
1) Las condiciones para el juicio son: El nombre del nodo padre del objeto actual = 'iNextNo'
…
2) Si queda una hoja secundaria, la fórmula es:
La izquierda del nodo actual = la izquierda del nodo padre + el ancho total de la hoja secundaria izquierda del nodo actual + el ancho del nodo actual
3) Si no hay una hoja secundaria izquierda, pero hay una hoja secundaria derecha , la fórmula es:
La izquierda del nodo actual = la izquierda del nodo principal + el ancho total de la hoja secundaria derecha del nodo actual
4) Si el nodo actual en sí es una hoja, la fórmula es:
La izquierda del nodo actual = la izquierda del nodo padre + el ancho del nodo actual...
Las fórmulas (2) y (3) obtienen la izquierda del nodo actual, y también necesitamos obtener la parte superior del nodo actual.
Fórmula muy simple: parte superior del nodo actual = parte superior del nodo principal + desplazamiento (80)
Idea de árbol binario (3)
Ideas de posicionamiento para conectar líneas:
(1) Encuentre las posiciones del nodo actual y el nodo principal (2) Determine si el nodo actual es el nodo secundario izquierdo o el nodo secundario derecho del nodo principal (3) Dibuje una línea
Algunas variables se definen aquí.
objOval //El nodo actual es un objeto
objParentOval //El nodo padre del objeto actual es un objeto
objLine //La línea actual es un objeto
Fórmula de posicionamiento de línea:
from="x1,y1" to="x2,y2" es la forma de posicionar líneas en VML.
El nodo actual es el nodo secundario izquierdo del nodo principal, entonces la fórmula es:
desde = izquierda del nodo principal + desplazamiento (15), parte superior del nodo principal + desplazamiento (32)
a = izquierda + desplazamiento (30) del nodo principal, arriba - desplazamiento (2) del nodo principal.
El nodo actual es el nodo secundario derecho del nodo principal, entonces la fórmula es:
desde = izquierda del nodo principal + desplazamiento (35), parte superior del nodo principal + desplazamiento (32)
a = izquierda del nodo principal + desplazamiento (20), parte superior del nodo principal - desplazamiento (2)
Eso es todo lo que puedo pensar.
Sería mucho más sencillo si hiciéramos un diagrama de estructura de la empresa.
La siguiente es idea de Cy Young, y solo voy a profundizar un poco más en su base.
Primero calcule la cantidad de nodos en el nivel inferior para obtener el ancho,
La posición del nodo superior debe calcularse en función de su afiliación, de forma recursiva.
Los nodos en cada nivel deben ordenarse según su afiliación. Primero, establezca el "valor básico" = el nodo debe estar desplazado hacia la derecha. El valor izquierdo de cada nodo que contiene nodos secundarios es igual a la mitad del ancho del nodo. posee más el valor básico.
Posdata:
Por alguna razón, Internet ha estado mal últimamente. Pase más tiempo fuera de línea que en línea.
Por tanto, el código no se ha simplificado, de hecho, todavía quedan muchas funciones por mejorar, como por ejemplo:
Debe agregar un menú contextual. El menú contextual contiene la capacidad de crear nuevos nodos, modificar nombres de nodos, cambiar asociaciones, etc. Puede hacer clic derecho en cada nodo para abrir el menú contextual de este nodo. .
explicar:
1) flow2.xml es un archivo de datos, creo que no habrá ningún problema para todos.
2) flow2.xsl es un archivo de formato, hay varias cosas a las que prestar atención.
(1) En el script:
(1) <xsl:value-of select="./iProcess/text()" />;
(2) {./iProcess/text()}
Las funciones de (1) y (2) son devolver el valor de cadena de la expresión dada por el parámetro de selección.
Sus condiciones de búsqueda son las mismas, por lo que los valores devueltos también son los mismos.
Es sólo que sus formas de escritura son diferentes según las ocasiones en que se utilizan.
<xsl:apply-templates select="equipo" order-by="blue_ID"/>
Por ejemplo, queremos generar el siguiente código
<div nombre="valor de parámetro">Contenido</div>
Suponemos que el nombre es "nombre" y el valor del parámetro es el valor del libro de nodos secundarios bajo el nodo actual en los datos XML.
La primera forma de escribirlo es agregar primero el nombre del atributo y luego el valor del parámetro.
<div>
<xsl:nombre del atributo="nombre">
<xsl:valor-de seleccionar="./book/text()"/> </xsl:atributo>
contenido
</div>
La segunda forma de escribir es agregar directamente el nombre del atributo y el valor del parámetro.
<div name="{./book/text()}">Contenido</div>
Para un uso específico, puedes ver los ejemplos en el código que escribí.
XSL está en el estándar oficial xmlns:xsl=" http://www.w3.org/1999/XSL/Transform "
<xsl:value-of select="./book/text()"/>
La función es: simplemente escriba su valor de texto y
<xsl:valor-de seleccionar="./libro"/>
Muestra su valor de texto y el contenido de todos sus nodos secundarios.
Puede probarlo y generar uno con nodos secundarios y otro sin nodos secundarios para ver si los resultados mostrados son los mismos.
(2) Nota:
IE5 no admite <tag att="{xpath}">
quiero usar
Es necesario utilizar el espacio de nombres
<tag><xsl:attribute name="att"><xsl:value-of select="xpath"></xsl:attribute>
xmlns:xsl=" http://www.w3.org/TR/WD-xsl "
<?xml versión="1.0" codificación="gb2312" ?>
Una cosa más:
La codificación="gb2312" rara vez se agrega al código que se muestra en la mayoría de los libros de texto XML.
Por lo tanto, cuando usamos chino en XML, se informará un error. El motivo es que esta declaración no está escrita.
posdata:
De lo que estoy hablando aquí es de una forma de pensar. Si haces una analogía, naturalmente te resultará útil.