如何动态地在网页中的图像上放置不同的模式。

时间:2009-11-04 06:22:17

标签: html asp.net-mvc image dhtml jpeg

我有

  1. 一堆布料图案(简单的jpg文件)
  2. 字母表中每个字母的图像(空白背景)
  3. 我基本上想要一个类似于此的页面: http://www.craftcuts.com/hand-painted-wooden-letters-single-patterns.html

    但不是将其作为静态页面,我希望用户能够:

    1. 输入名称
    2. 选择一种模式(其中一个jpg文件)
    3. 然后让它以该模式显示该名称。

      显然我可以为每个字母组合创建单独的jpgs(现在我的每个字母都有白色背面颜色的jpg)和模式但是我想知道是否有更优雅的编码方式它动态地将一个图像放在另一个图像上。


      编辑:在我的帖子中,我认为这必须是一个前端的东西(javascript),但如果它让它变得更容易(因为有些人问什么是后端),我的后端是一个asp.net-mvc所以如果有一些解决方案可以在服务器端构建它并发送到客户端,我也非常乐意使用它。 < / p>

9 个答案:

答案 0 :(得分:15)

您可以使用CSS将背景图像应用于图像,然后使用大量透明的.png图像作为字母。

我嘲笑它:

<!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>

你也可以see it in action

alt text http://www.subdimension.co.uk/files/1/SO/A.png&lt;这是字母剪纸之一(很难看到!)

alt text http://www.subdimension.co.uk/files/1/SO/leaves.png和其中一种背景模式。

我对G很无聊,所以你只能写出包含字母ag的单词,它也有点懒,因为它只做大写但只有2种模式但希望它应该足以给你一个想法

答案 1 :(得分:11)

您可以使用ImageMagick库来制作您和用户心中所需叠加的任意组合。这样,您不仅限于使用CSS可以实现的简单。

ImageMagick examples

答案 2 :(得分:6)

通过Javascript执行此操作的最简单方法可能是使用每个字母的图像蒙版并将其应用于模式之上。通过图像蒙版,我指的是一个完全黑色(或白色,或任何你喜欢的)的简单图像,其中“切出”的透明部分呈字母形状。您可以简单地将其覆盖在模式文件上以获得想要的效果。

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

您可以动态更改img srcdiv background url以切换模式和字母。您还可以根据用户输入动态创建新的divs

请注意,由于透明的PNG,这在IE6中无法轻松实现。

或者,您可以使用类似gd之类的内容在服务器上动态生成图像,这会更复杂一些,但最终会更灵活。

答案 3 :(得分:4)

要让用户能够输入自己的名字,您需要一个文本字段。您还需要一个触发Javascript函数的按钮,该函数检查文本字段的值并呈现字母图像。

您可以使用以下代码创建字母。您将需要一个带有“textfield”和div的文本字段来使用id“output”呈现结果,您可以更改其中的内容。我建议使用select元素来存储模式选项(本例中为#patternChooser)

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);
    }
}

您可以使用以下CSS对字母应用一些定位(调整图像的高度和高度):

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

你需要像这样命名你的图像:flowerpattern_a.png,brickpattern_j.png等。

如果您希望字母实时显示,您可以使用Javascript的onkeyup()来触发检查文本字段值的最后一个字符并为其创建元素的函数。

<强>精灵

您还可以使用精灵来提高性能。将字母的所有图像放入一个图像中。您将此图像设置为每个字母的背景。 快速阅读CSS精灵:http://css-tricks.com/css-sprites/ 您可以将background-image: url(sprite.png);添加到上面的CSS代码段中。 您不需要使用Javascript设置backgroundImage,而是需要设置字母的背景位置(letter.style.background-position = '100px 200px'

字体嵌入

如果您要使用字体:有许多字体嵌入选项,例如TypefaceCufon。我觉得最愉快的一个是使用 font-face 。它很快,文本的行为与任何其他文本一样。

如果你有.TTF Truetype字体,你需要将字体转换为.EOT以便与Internet Explorer一起使用。您还可以为完整的浏览器覆盖添加SVG字体。它实际上非常简单:您只需将以下代码段添加到样式表的顶部,如下所示:

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

这种技术的优势在于它易于使用,您可以完全控制渲染文本,就像您网站上的任何其他文本一样。您可以设置字体大小,字母间距等Here's a good read about font-face font embedding。 您可以使用Microsoft WEFTTTF2EOT创建.EOT字体。

例如,您的代码可能如下所示。

<强> 的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');
}

现在唯一剩下的就是转换字体并将它们导入样式表。

当然,您可以选择使用任何其他字体嵌入方法。 Here's an article about font-embedding options但是快速的Google也会向您显示选项。

答案 4 :(得分:1)

如果允许在后端使用某些东西,这是一个java解决方案。您只需要使用字体(name.ttf)键入字母,但我认为您拥有它:

(这是在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();

答案 5 :(得分:1)

即使在服务器上,这也不是一个小问题,因为不可能使用颜色掩码直接填充(),这实际上是你需要的。

如果字母图像是非白色的话,我会更快地遍历现有的像素,进行查找并将图案像素写入生成的图像:

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);
}

}

然后找到一个命名方案,在创建后将这些缓存在磁盘上,这样你只需要渲染每个模式&lt; - &gt;字母组合一次。

答案 6 :(得分:1)

GDI +在ASP.NET下运行良好。 (WPF曾经,但随后被服务包破坏。不确定它现在是否正在运行。)

构建映像服务器端非常简单 - 技巧是将它们链接到客户端请求。我使用了堆栈表示 - 我的文章在这里:

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

答案 7 :(得分:1)

在用OO(海报)确认之后,我想把Flash混合在一起。

Flash的优势在于它具有非常好的抗锯齿和令人敬畏的排版支持(特别是自CS4以来)。您可以选择将整个界面放在Flash中直接键入图案化字母,或者让swf根据指定名称和图案的参数渲染结果。

就个人而言,我会在Flash中完成整个过程,为接口提供可选模式,例如JSON。但是你可以采取的最基本步骤是

创建一个表单,其中包含名称输入和模式选择框

显示参数 patterntype.swf的flash文件?name = flash&amp; pattern = disco.png

基本概念是将Text设置为模式的掩码。 我在flash中做了一个快速测试来测试平铺模式的性能(如果实际上有效)

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);
                }
            }
        }

    }
}

当所有内容符合用户的意愿时,您可以从结果中创建一个新的Bitmap对象,并将数据发送到服务器,该服务器可以将数据直接写入位图文件(也可以使用jpeg)。

有些东西可以卖得更多一些:

  • 您可以旋转文字
  • 使用异国情调字体
  • 每个字母使用不同的图案
  • 缩放文字
  • 使用自定义图片过滤器
  • 在3d空间中移动(x,y,z平移旋转,透视)
  • 将结果另存为图像

答案 8 :(得分:0)

阅读下面的链接,您将找到动态装载机详细信息以及示例 http://thecodecentral.com/2008/02/21/a-useful-javascript-image-loader