En este artículo veremos cómo crear imágenes dinámicamente desde una página web. A modo de ejemplo desarrollaremos un control para dibujar gráficas de forma dinámica.
Este control para generar una gráfica es bastante sencillo, pero a partir de él se podrían construir otros más complejos para generar diagramas de caja, diagramas de sectores, etc.
En nuestro proyecto (del tipo aplicación web) añadiremos una nueva clase a la que llamaremos Imagen, y que heredará del control web Image.
Muchas tienen valores por defecto, para que se pueda mostrar la gráfica en tiempo de diseño antes de asignar valores a sus propiedades.
Dim mValores() As Integer = {100, 25, 80, 50, 45}
Public Property Valores() As Integer()
Get
Return mValores
End Get
Set(ByVal Value As Integer())
mValores = Value
End Set
End Property
Dim mColorFondo As Color = Color.Khaki
Public Property ColorFondo() As Color
Get
Return mColorFondo
End Get
Set(ByVal Value As Color)
mColorFondo = Value
End Set
End Property
Dim mColorGraficas As Color = Color.LightBlue
Public Property ColorGraficas() As Color
Get
Return mColorGraficas
End Get
Set(ByVal Value As Color)
mColorGraficas = Value
End Set
End Property
Dim mAnchoBarras As Integer = 20
Public Property AnchoBarras() As Integer
Get
Return mAnchoBarras
End Get
Set(ByVal Value As Integer)
mAnchoBarras = Value
End Set
End Property
Dim mSeparacionEntreBarras As Integer = 20
Public Property SeparacionEntreBarras() As Integer
Get
Return mSeparacionEntreBarras
End Get
Set(ByVal Value As Integer)
mSeparacionEntreBarras = Value
End Set
End Property
Dim mEncabezado As String
Public Property Encabezado() as string
Get
return mEncabezado
End Get
Set(ByVal Value As string)
mEncabezado = Value
End Set
End Property
Dim mPie As String
Public Property Pie() As String
Get
Return mPie
End Get
Set(ByVal Value As String)
mPie = Value
End Set
End Property
Dim mMostrarValores As Boolean
Public Property MostrarValores() As Boolean
Get
Return mMostrarValores
End Get
Set(ByVal Value As Boolean)
mMostrarValores = Value
End Set
End Property
En el constructor de la clase inicializaremos sus dimensiones para que tenga un tamaño inicial.
Como ya comentamos anteriormente, la encargada de dibujar la imagen es la página DibujaImagen, la cual recibirá por querystring todos los parámetros que requiere para dibujar correctamente la gráfica. La llamada a esta página la realizaremos en el procedimiento Render de la clase Imagen, el cual tendremos que sobrescribir.
Option Explicit On
Option Strict On
Public Class DibujaImagen
Inherits System.Web.UI.Page
#Region " Código generado por el Diseñador de Web Forms "
'El Diseñador de Web Forms requiere esta llamada.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
End Sub
'NOTA: el Diseñador de Web Forms necesita la siguiente declaración del marcador de posición.
'No se debe eliminar o mover.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: el Diseñador de Web Forms requiere esta llamada de método
'No la modifique con el editor de código.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Introducir aquí el código de usuario para inicializar la página
Const MARGEN_SUPERIOR As Integer = 20
Const MARGEN_INFERIOR As Integer = 20
Const MARGEN_IZQUIERDO As Integer = 30 ' 20
Const MARGEN_DERECHO As Integer = 20
Dim ancho As Integer
Dim alto As Integer
Dim separacionEntreBarras As Integer
Dim anchoBarras As Integer
Dim colorFondo As String
Dim colorGraficas As String
Dim i As Integer
Dim strValores As String
Dim valores() As String
Dim valor As Integer
Dim maximo As Integer
Dim intervalo As Integer
Dim cadena As String
Dim mostrarValores As Boolean
Dim imgBitmap As Bitmap
Dim graficos As Graphics
Dim lapiz As New Pen(Color.Black)
Dim brocha As SolidBrush = New SolidBrush(Color.Black)
Dim brochaColorGraficas As SolidBrush
colorFondo = Request.Params("ColorFondo")
colorGraficas = Request.Params("ColorGraficas")
ancho = CInt(Request.Params("Ancho"))
alto = CInt(Request.Params("Alto"))
separacionEntreBarras = CInt(Request.Params("SeparacionEntreBarras"))
anchoBarras = CInt(Request.Params("AnchoBarras"))
mostrarValores = CBool(Request.Params("mostrarValores"))
cadena = Request.Params("Cadena")
brochaColorGraficas = New SolidBrush(Color.FromName(colorGraficas))
imgBitmap = New Bitmap(ancho, alto)
graficos = Graphics.FromImage(imgBitmap)
graficos.Clear(Color.FromName(colorFondo))
strValores = Request.Params("Valores")
valores = strValores.Split("_".ToCharArray)
maximo = Integer.MinValue
For i = 0 To valores.GetUpperBound(0)
If CInt(valores(i)) > maximo Then maximo = CInt(valores(i))
Next
maximo = CInt(maximo * 1.2)
intervalo = CInt(maximo / 5)
graficos.DrawLine(lapiz, MARGEN_IZQUIERDO, MARGEN_SUPERIOR, MARGEN_IZQUIERDO, alto - MARGEN_INFERIOR) 'eje vertical
graficos.DrawLine(lapiz, MARGEN_IZQUIERDO - 5, alto - MARGEN_INFERIOR, ancho - MARGEN_DERECHO, alto - MARGEN_INFERIOR) 'eje horizontal
graficos.DrawLine(lapiz, MARGEN_IZQUIERDO - 5, MARGEN_SUPERIOR, MARGEN_IZQUIERDO + 5, MARGEN_SUPERIOR)
graficos.DrawLine(lapiz, MARGEN_IZQUIERDO - 5, MARGEN_SUPERIOR + CInt((alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5), MARGEN_IZQUIERDO + 5, MARGEN_SUPERIOR + CInt((alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5))
graficos.DrawLine(lapiz, MARGEN_IZQUIERDO - 5, MARGEN_SUPERIOR + CInt(2 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5), MARGEN_IZQUIERDO + 5, MARGEN_SUPERIOR + CInt(2 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5))
graficos.DrawLine(lapiz, MARGEN_IZQUIERDO - 5, MARGEN_SUPERIOR + CInt(3 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5), MARGEN_IZQUIERDO + 5, MARGEN_SUPERIOR + CInt(3 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5))
graficos.DrawLine(lapiz, MARGEN_IZQUIERDO - 5, MARGEN_SUPERIOR + CInt(4 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5), MARGEN_IZQUIERDO + 5, MARGEN_SUPERIOR + CInt(4 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5))
graficos.DrawString((intervalo * 5).ToString, New Font("Arial", 10), brocha, 2, MARGEN_SUPERIOR - 7)
graficos.DrawString((intervalo * 4).ToString, New Font("Arial", 10), brocha, 2, CInt((alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5) + MARGEN_SUPERIOR - 7)
graficos.DrawString((intervalo * 3).ToString, New Font("Arial", 10), brocha, 2, CInt(2 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5) + MARGEN_SUPERIOR - 7)
graficos.DrawString((intervalo * 2).ToString, New Font("Arial", 10), brocha, 2, CInt(3 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5) + MARGEN_SUPERIOR - 7)
graficos.DrawString(intervalo.ToString, New Font("Arial", 10), brocha, 2, CInt(4 * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / 5) + MARGEN_SUPERIOR - 7)
Dim puntos(3) As PointF
Dim puntos2(3) As PointF
For i = 0 To valores.GetUpperBound(0)
puntos(0).X = MARGEN_IZQUIERDO + 20 + (i * (separacionEntreBarras + anchoBarras)) + 10
puntos(0).Y = alto - MARGEN_INFERIOR - CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo) - 10
puntos(1).X = MARGEN_IZQUIERDO + 20 + (i * (separacionEntreBarras + anchoBarras)) + anchoBarras + 10
puntos(1).Y = alto - MARGEN_INFERIOR - CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo) - 10
puntos(2).X = MARGEN_IZQUIERDO + 20 + (i * (separacionEntreBarras + anchoBarras)) + anchoBarras
puntos(2).Y = alto - MARGEN_INFERIOR - CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo)
puntos(3).X = MARGEN_IZQUIERDO + 20 + (i * (separacionEntreBarras + anchoBarras))
puntos(3).Y = alto - MARGEN_INFERIOR - CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo)
puntos2(0).X = puntos(2).X
puntos2(0).Y = puntos(2).Y
puntos2(1).X = puntos(1).X
puntos2(1).Y = puntos(1).Y
puntos2(2).X = puntos(1).X
puntos2(2).Y = alto - MARGEN_INFERIOR - 10
puntos2(3).X = puntos(2).X
puntos2(3).Y = alto - MARGEN_INFERIOR
Dim camino As New Drawing2D.GraphicsPath
Dim camino2 As New Drawing2D.GraphicsPath
camino.AddPolygon(puntos)
camino2.AddPolygon(puntos2)
graficos.FillRectangle(brochaColorGraficas, MARGEN_IZQUIERDO + 20 + (i * (separacionEntreBarras + anchoBarras)), alto - MARGEN_INFERIOR - CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo), anchoBarras, CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo))
graficos.FillPath(brochaColorGraficas, camino)
graficos.FillPath(brochaColorGraficas, camino2)
graficos.DrawPath(lapiz, camino)
graficos.DrawPath(lapiz, camino2)
graficos.DrawRectangle(lapiz, MARGEN_IZQUIERDO + 20 + (i * (separacionEntreBarras + anchoBarras)), alto - MARGEN_INFERIOR - CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo), anchoBarras, CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo))
If mostrarValores Then
graficos.DrawString(valores(i), New Font("Arial", 8), brocha, MARGEN_IZQUIERDO + 30 + (i * (separacionEntreBarras + anchoBarras)), alto - MARGEN_INFERIOR - CInt(CInt(valores(i)) * (alto - (MARGEN_SUPERIOR + MARGEN_INFERIOR)) / maximo) - 25)
End If
Next
graficos.DrawString(Request.Params("Pie"), New Font("Arial", 8), brocha, MARGEN_IZQUIERDO, alto - 15)
graficos.DrawString(Request.Params("Encabezado"), New Font("Arial", 8), brocha, MARGEN_IZQUIERDO, 5)
Response.ContentType = "image/jpeg"
imgBitmap.Save(Response.OutputStream, Imaging.ImageFormat.Jpeg)
brochaColorGraficas.Dispose()
brocha.Dispose()
lapiz.Dispose()
graficos.Dispose()
imgBitmap.Dispose()
End Sub
End Class