2009-11-04 5 views
7

hoCome puoi inserire dinamicamente diversi modelli sulle immagini in una pagina web.

  1. Un gruppo di modelli di tessuto (semplici file jpg)
  2. un'immagine per ogni lettera dell'alfabeto (sfondo bianco bianco)

ho essenzialmente desidera avere una pagina simile a questo: http://www.craftcuts.com/hand-painted-wooden-letters-single-patterns.html

ma invece di avere come una pagina statica, desidero un utente sia in grado di:

0.123.
  1. Digitare un nome
  2. Scegliere un modello (uno dei file jpg)

e poi lo hanno visualizzare quel nome in quel modello.

Ovviamente ho potuto creare jpgs separati per ogni combinazione di lettere (in questo momento ho un jpg per ogni lettera con la parte posteriore di colore bianco) e dei modelli, ma volevo sapere se ci fosse un modo più elegante di codificare questo fino a farlo mettere dinamicamente un'immagine sulla lettera nell'altra.


EDIT: Nel mio post iniziale, ho pensato che questo avrebbe dovuto essere una cosa front end (javascript), ma se lo rende affatto più facile (come alcune persone hanno chiesto qual è il backend), il mio back end è un asp.net-mvc, quindi se c'è qualche soluzione per crearlo sul server e spedirlo al cliente, sono più che felice di usare anche quello.

+0

È necessario eseguire questa operazione in html puro, poiché l'esempio mostra le immagini generate. –

+0

cosa intendi. . deve solo finire su un sito web, quindi fintanto che la sua dinamica in qualche modo funzionerà, – leora

+0

Flash è un'opzione? perché sono sicuro che ti darebbe i migliori risultati riguardo la tipografia e l'anti-aliasing. – Les

risposta

15

È possibile applicare le immagini di sfondo alle immagini usando i CSS, quindi usa un carico di immagini .png trasparenti per le lettere.

ho deriso in su:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<title>Untitled Document</title> 

<style type="text/css"> 

img.leaves 
{ 
    background:url("leaves.png"); 
} 
img.lights 
{ 
    background:url("lights.png"); 
} 

</style> 

<script type="text/javascript"> 

function makeText() 
{ 
    var text = document.getElementById('text').value.toUpperCase(); 
    var pattern = document.getElementById('pattern').value; 

    for(var i=0; i<text.length; i++) 
    { 
     var img = document.createElement('img'); 
     img.src=text[i]+'.png'; 
     img.className=pattern; 
     document.getElementById('textArea').appendChild(img); 
    } 

    return false; 
} 

</script> 

</head> 

<body> 

<form onsubmit="return makeText();"> 
<p><label for="text">Enter your text</label> <input type="text" name="text" id="text" size="20"></p> 
<p><label for="pattern">Choose a pattern</label> <select id="pattern"><option value="leaves">Leaves</option><option value="lights">Lights</option></select></p> 
<p><input type="submit" value="Make!"></p> 
</form> 

<div id="textArea"></div> 

</body> 
</html> 

e si può anche see it in action.

alt text http://www.subdimension.co.uk/files/1/SO/A.png < questo è uno dei ritagli lettera (difficile da vedere!)

alt text http://www.subdimension.co.uk/files/1/SO/leaves.png e uno dei modelli di sfondo.

Mi annoiavo in G, quindi puoi scrivere solo parole che contengono le lettere ag, è anche un po 'pigro in quanto fa solo maiuscole e ci sono solo 2 motivi, ma si spera che dovrebbe essere sufficiente per darti un idea

+1

Sì, questo è totalmente ciò che stavo scrivendo usando una maschera negativa. Questo è l'approccio più flessibile, è possibile generare facilmente un elenco dei modelli leggendo un elenco di directory. Se hai bisogno di piena compatibilità PNG in IE6 usa dd_belated http://www.dillerdesign.com/experiment/DD_belatedPNG/ – Tom

+0

Potresti anche salvare le lettere della maschera come un'unica grande immagine e usarla come sprite. Quindi ogni lettera sarebbe un DIV con l'immagine di sfondo spostata nella posizione corretta. Ciò renderebbe ancora più semplice la creazione di alcune maschere tramite caratteri diversi. Detto questo, non sarebbe perfetto, dato che le tue lettere basate su immagini finiranno per essere monospaced. Guarderei forse usando Flash per questo. –

+1

+1 per una soluzione elegante e anche per prendere la strada lunga di mettere su un campione - bravo! – Till

6

Il modo più semplice per farlo tramite Javascript è probabilmente quello di avere una maschera immagine di ogni lettera e applicarla sopra un modello. Per maschera immagine intendo un'immagine semplice completamente nera (o bianca, o qualsiasi altra cosa tu preferisca) con una parte trasparente "ritagliata" nella forma della lettera. Puoi semplicemente sovrapporlo al file di pattern per ottenere l'effetto desiderato.

<div style="background: url(pattern.jpg)"> 
    <img src="letter_a.png" /> 
</div> 

È possibile modificare dinamicamente il img src e div background url di cambiare i modelli e le lettere. È inoltre possibile creare dinamicamente nuovo divs in base all'input dell'utente.

Si noti che questo non funzionerà facilmente in IE6 a causa del PNG trasparente.

In alternativa, è possibile generare l'immagine dinamicamente sul server utilizzando qualcosa come gd, che sarebbe un po 'più coinvolto, ma in definitiva più flessibile.

+0

non seguo abbastanza qui. avete dei collegamenti che mostrano esempi di questo? – leora

+1

1. Mettere il motivo sullo sfondo. 2. Metti un'immagine "tagliata" sopra. 3. Vedi il modello attraverso i fori nel "cut out". Esempio di esempio correlato qui: http://ifohdesigns.com/blog/tutorials/transparent-png-mask – deceze

+0

Mentre in questo modo e png trasparenti forniscono certamente un modo pulito e flessibile, non ti permetterà di utilizzare lettere decorate variate come visto nell'esempio in cui le lettere non differiscono solo nel modello ma anche nella forma. – richard

11

È possibile utilizzare le librerie di ImageMagick per creare qualsiasi combinazione di sovrapposizioni desiderate dai desideri dei vostri utenti e dei vostri utenti. In questo modo, non sei limitato a qualcosa di semplice che può essere raggiunto con i CSS.

ImageMagick examples

+0

stai suggerendo di usare l'immagine composita nel link? – leora

+0

Qualcosa del genere. Ho usato ImageMagick per implementare watermarking, che è molto simile a questo. –

+0

@oo: Artem sta suggerendo di generare le immagini sul server usando ImageMagick, presumibilmente dopo che l'utente ha richiesto una determinata combinazione di testo e pattern. Questo può essere fatto abbastanza facilmente con ImageMagick. –

4

gli utenti siano in grado di digitare in nome proprio avrete bisogno di un campo di testo. Avrai anche bisogno di un pulsante che attivi una funzione Javascript che controlli il valore del campo di testo e renda le immagini delle lettere.

È possibile utilizzare il seguente codice per creare le lettere. Avrai bisogno di un campo di testo con l'id 'textfield' e un div per rendere i risultati con l'id 'output', che naturalmente puoi cambiare. Mi consiglia di utilizzare un elemento di selezione per memorizzare le opzioni di modello (#patternChooser in questo esempio)

function renderName() 
{ 
    // Get the name to be rendered and the chosen pattern 
    var text = document.getElementById('textfield').value; 
    var pattern = document.getElementById('patternChooser').value; 

    // Iterate over the name and create an element for each letter 
    for(i = 0; i < text.length; i++) 
    { 
     var letter = document.createElement('div'); 
     letter.style.backgroundImage = 'url(' + pattern + '_' + text[i] + ')'; 

     document.getElementById('output').appendChild(letter); 
    } 
} 

È possibile utilizzare il seguente CSS per applicare un po 'di posizionamento alle lettere (regolare l'altezza con e a quella delle immagini) :

#output div 
{ 
    margin-left: 10px; 
    width: 50px; 
    height: 100px; 
    float: left; 
} 

sarà necessario dare un nome alle immagini come questa: flowerpattern_a.png, brickpattern_j.png, ecc

Se si desidera che le lettere vengano visualizzati in tempo reale è possibile utilizzare onkeyup() di Javascript per sparare una funzione che controlla l'ultimo carattere del valore del campo di testo e crea un elemento per esso.

Sprites

È anche possibile utilizzare uno sprite per aumentare le prestazioni. Metti tutte le immagini per le lettere in un'unica immagine. Imposta questa immagine come sfondo per ogni lettera. Lettura rapida su sprite CSS: http://css-tricks.com/css-sprites/ È possibile aggiungere background-image: url(sprite.png); allo snippet CSS sopra. Invece di limitarsi a impostare un BackgroundImage con Javascript, è necessario impostare la posizione della lettera sfondo (letter.style.background-position = '100px 200px')

Integrazione dei font

Se hai caratteri da usare: ci sono molte opzioni di font embedding come Typeface e Cufon. Quello che trovo più piacevole con cui lavorare è l'uso di font-face. È veloce e il testo si comporterà come qualsiasi altro testo.

Se hai il tuo carattere .TTF Truetype, dovrai convertire il carattere in .EOT per l'uso con Internet Explorer. È anche possibile aggiungere font SVG per la copertura completa del browser. In realtà è molto semplice: basta aggiungere il seguente frammento alla parte superiore del vostro foglio di stile come questo:

@font-face { 
    font-family: 'GothicCustom'; 
    src: url("LeagueGothic.eot"); 
    src: local('League Gothic'), 
     url("LeagueGothic.svg#lg") format('svg'), 
     url("LeagueGothic.otf") format('opentype'); 
} 

Il vantaggio di questa tecnica è che è facile da usare e si ha pieno controllo sul testo reso, come ogni altro testo sul tuo sito web. È possibile impostare la dimensione del carattere, la spaziatura delle lettere ecc. Here's a good read about font-face font embedding. È possibile utilizzare Microsoft WEFT o TTF2EOT per creare caratteri .EOT.

Ad esempio, il codice potrebbe essere simile a questo.

Javascript

function renderName() 
{ 
    // Get the name to be rendered and the chosen pattern 
    var text = document.getElementById('textfield').value; 
    var pattern = document.getElementById('patternChooser').value; 

    // Render the text with a class 
    for(i = 0; i < text.length; i++) 
    { 
     var output = document.getElementById('output'); 

     output.style.fontFamily = pattern; 
     output.innerHTML = text; 
    } 
} 

HTML

<form> 
    <input id="textfield" type="text" /> 

    <select id="patternChooser"> 
     <option>Flowers</option> 
     <option>Brick</option> 
     <option>Decorative</option> 
    </select> 

    <input type="button" onclick="renderName()" /> 
</form> 

<div id="output"></div> 

CSS

@font-face { 
    font-family: 'Decorative'; 
    src: url("decorative.eot"); 
    src: local('Decorative'), 
     url("Decorative.svg#lg") format('svg'), 
     url("Decorative.otf") format('opentype'); 
} 

Ora l'unica cosa che rimane è la conversione dei caratteri e l'importazione nel foglio di stile.

Ovviamente puoi scegliere di utilizzare qualsiasi altro metodo di inclusione di font. Here's an article about font-embedding options ma un veloce Google ti mostrerà anche le opzioni.

+1

Non stai sostanzialmente suggerendo, con l'aggiunta di sprite, l'approccio che l'OP sta cercando di trovare una soluzione più elegante di? – philfreo

+0

penso di essere d'accordo. . nel tuo esempio ho bisogno di ogni combinazione di lettere e pre-configurazione del pattern? – leora

+0

In questo esempio è necessario salvare un png per ogni lettera nel modello o creare uno sprite per ciascun motivo. Ho aggiunto l'opzione di incorporamento dei caratteri con cui dovrai solo offrire i caratteri e importarli nel tuo foglio di stile. – richard

1

Se si è permesso di usare qualcosa nel back-end, ecco una soluzione Java. Avrete solo bisogno il tipo di carattere (name.ttf) con cui si digitano le lettere, ma suppongo avete:

(questo è all'interno di un metodo servlet doGet)

 
String text = "A letter, or any text here"; 
File texture = new File(patternTexturePath); 

File fontFile = new File(filePath); 
Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile); 
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
ge.registerFont(font); 


BufferedImage buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 

g2 = buffer.createGraphics(); 
g2.clearRect(0, 0, width, height); 
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
        RenderingHints.VALUE_ANTIALIAS_ON); 
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
        RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
g2.setRenderingHint(RenderingHints.KEY_RENDERING, 
         RenderingHints.VALUE_RENDER_QUALITY); 

FontRenderContext fc = g2.getFontRenderContext(); 
Rectangle2D bounds = font.getStringBounds(text, fc); 

AttributedString attrStr = new AttributedString(text); 
Rectangle r = new Rectangle(0, 0, width, height); 
attrStr.addAttribute(TextAttribute.FOREGROUND, new TexturePaint(ImageIO.read(texture), r)); 
attrStr.addAttribute(TextAttribute.FONT, font); 
g2.drawString(attrStr.getIterator(), 0, (int) -bounds.getY()); 

response.setContentType("image/png"); 
ImageIO.write(buffer, "png", response.getOutputStream()); 
response.getOutputStream().close(); 
1

Anche sul server questo non è un problema banale, in quanto non è possibile eseguire una Fill() diretta utilizzando una maschera a colori, che è essenzialmente ciò di cui hai bisogno.

avrei ciclo più presto nel corso dei pixel esistenti, fare una ricerca e scrivere il pixel modello per l'immagine risultante se l'immagine lettera è non-bianco:

Graphics g = Graphics.FromImage(letterImg); 
Brush brush = new System.Drawing.TextureBrush(patternImg); 
for (int x=0;i<letterImg.Width;i++) 
    for (int y=0;y<letterImg.Height;y++) 
{ 
    Color mask = img.GetPixel(x,y); 
    //Color pattern = patternImg.GetPixel(x % patternImg.Width, y % patternImg.Height); 
    if (mask != Color.White) 
{ 
    g.FillRectagle(brush,x,y,1,1); 
} 

} 

e poi trovare uno schema di denominazione di cache di questi sul disco dopo la creazione, quindi è sufficiente eseguire il rendering di ciascun motivo < -> combinazione di lettere una volta.

1

GDI + funziona correttamente con ASP.NET. (Solitamente WPF, ma poi è stato rotto con un service pack. Non sono sicuro che funzioni di nuovo ora).

Costruire immagini lato server è piuttosto semplice, il trucco è collegarle alle richieste lato client. Ho fatto uso di una rappresentazione stack - il mio articolo qui:

http://www.hackification.com/2008/10/29/stack-based-processing-part-2/

1

Dopo aver confermato con OO (il manifesto) ho voluto gettare Flash nel mix.

Flash ha il vantaggio di avere un ottimo anti-aliasing e un ottimo supporto tipografico (specialmente da CS4). È possibile scegliere di avere l'intera interfaccia in Flash in cui si digitano direttamente le lettere con motivi o semplicemente si deve rendere il risultato swf in base ai parametri che specificano il nome e il motivo.

Personalmente farei il tutto in Flash, fornendo l'interfaccia con i modelli opzionali con per esempio JSON. Ma i passaggi più elementari si potrebbe prendere sono

creare un modulo con ingresso per il nome e una casella di selezione per i modelli

di visualizzazione del file flash con i parametri patterntype.swf? Name = Flash & pattern = disco.png

Il concetto di base è avere il set di testo come maschera per il modello. Ho fatto un test rapido in flash per testare le prestazioni di piastrelle del modello (e se sarebbe effettivamente lavorare)

package { 

    import flash.display.MovieClip; 
    import flash.display.Loader; 
    import flash.net.URLRequest; 
    import flash.events.Event; 
    import flash.display.Sprite; 
    import flash.display.Bitmap; 
    import flash.display.BitmapData; 


    public class PatternType extends MovieClip { 
     /* library element, use the textfield to change the font */ 
     public var nameDisplay:NameDisplay; 

     private var loader:Loader; 

      /* parameters, you can pass these as request parameters, or make a javascript call to get/set them */ 
     private var pattern:String = "pattern.png"; 
     private var nameString:String = "Heidi Klum"; 
     private var container:MovieClip; 


     public function PatternType() { 
      container = new MovieClip(); 
      addChild(container); 

      nameDisplay = new NameDisplay(); 
      nameDisplay.txt.text = nameString; 
      nameDisplay.cacheAsBitmap = true; //mask wont work without this. 
      container.addChild(nameDisplay) 

      container.mask = nameDisplay; 

      loader = new Loader(); 
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handlePatternLoaded); 
      loader.load(new URLRequest(pattern)); 
     } 


     private function handlePatternLoaded(e:Event) { 
      trace("complete"); 
      var bmp:Bitmap = e.target.content as Bitmap; 

      var rows:int = Math.ceil(stage.stageHeight/bmp.height); 
      var cols:int = Math.ceil(stage.stageWidth/bmp.width); 

      //tile the texture 
      for(var i:int = 0; i < cols; i++) { 
       for(var j:Number = 0; j < rows; j++) { 
        var b:Bitmap = new Bitmap(bmp.bitmapData.clone()); 
        b.x = i * bmp.width; 
        b.y = j * bmp.height; 
        container.addChild(b); 
       } 
      } 
     } 

    } 
} 

Quando tutto è ai desideri degli utenti, è possibile creare un nuovo oggetto Bitmap dal risultato e invia i dati al server che può scrivere i dati direttamente in un file bitmap (è anche possibile jpeg).

Un paio di cose che potrebbero vendere Flash un po 'di più:

  • è possibile ruotare il testo
  • Usa font esotici
  • utilizzare diversi modelli per ogni lettera
  • scala
  • il testo
  • uso filtri immagine personalizzati
  • spostare nello spazio 3d (rotazione di traslazione x, y, z, prospettiva)
  • Salvare il risultato come immagine
+0

Flash è raramente la mia prima scelta, ma per questo particolare compito, è probabilmente l'opzione più ideale. –

Problemi correlati