JS Days 2025 is now live – Join 5,000+ devs for the premier virtual JavaScript event. Register Now

Creating Beautiful Drawings Using Sencha Ext JS – Part 1

December 8, 2015 2042 Views
Show

Many of you may already be familiar with the Sencha Charting package that comes with Sencha Ext JS. It allows you to quickly create great visualizations such as 3D Column Charts or 3D Pie Charts. Often, charts are not enough for your web applications, and you may need to create a flowchart, seat map, a schematic, or maybe an interactive animation in your app.

Creating Beautiful Drawings with Sencha Ext JS

Of course, you can use the HTML5 Canvas or SVG directly, but those often lead to issues on platforms that are not supported. Dealing with cross-browser issues, differences across regular and retina displays, animations, etc. is not an easy task. You may be able to use third party libraries that support multiple renderers and provide some useful abstractions, but quickly you’ll find yourself spending time dealing with integrations across those libraries.

Ext JS Charts comes with a drawing package that allows you to create arbitrary graphics and animations without worrying about which technology a particular browser uses to render your drawings. It automatically selects the most appropriate renderer (Canvas, SVG or VML) depending on your browser. Under the hood, the draw package follows HTML5 Canvas as the underlying API model. Canvas API calls are automatically translated to SVG or VML, if those engines are required.

In this series of articles, we will go over several features of the draw package that comes with Sencha Charts, and how they have been implemented, so you don’t have to deal with cross-browser compatibility issues.

A Simple Sprite

A sprite is a basic primitive which represents a graphical object that can be drawn. You can create a desired image by combining multiple sprites. There are many different kinds of sprites available in the Draw package. Each sprite type has various attributes that define how a sprite should look. For example, this is a rect sprite:

{
    xtype: 'draw',
    width: 250,
    height: 250,
    sprites: [{
        type: 'rect',
        x: 50,
        y: 50,
        width: 100,
        height: 100,
        lineWidth: 4,
        strokeStyle: 'green',
        fillStyle: 'yellow'
    }]
}

Sprite

Open in a Fiddle

Here the type: 'rect' corresponds to the sprite’s alias, and the rest of the config properties are sprite attributes. It’s important to note that sprite attributes are not configs. You’ll find out more about the differences between attributes and configs in subsequent parts of this series. For now, let’s just say they are processed and used differently.

The Draw Container

The draw xtype in our previous example corresponds to the Ext.draw.Container class. This is the container of the draw surfaces (instances of the Ext.draw.Surface) in which sprites are rendered.

Notice how we used the sprites config and not the items config of the draw container to add a rect sprite to it. This is because items of the draw container are its surfaces. And the sprites defined in the sprites config go into the default main surface. You can make a sprite go to a surface other than default, if you use sprite’s surface config (yes, this is not an attribute). For example:

{
    type: 'rect',
    surface: 'privateSurface',
    x: 50,
    y: 50,
    width: 100,
    height: 100,
    ...
}

The above will create a surface with ID privateSurface and the rect sprite will go into it, instead of the default ‘main’ surface. The surface config may also be an actual surface instance, which means you would add sprites via setSprites method after the draw container has been instantiated.

Please note that setSprites won’t remove sprites that were already added by the initial sprites config or by previous calls to setSprites. It will only add new sprites. This is because the sprites config is meant to be used declaratively. If you need to manipulate sprites, you can do this using surface methods.

Using Multiple Surfaces

The ability to have multiple surfaces is useful for performance (and battery life) reasons. Because changes to sprite attributes cause the whole surface (and all sprites in it) to re-render, it makes sense to group sprites by surface, so changes to one group of sprites will only trigger the surface they are in to re-render. The Sencha Chart package, which is built on top of the Draw package, heavily relies on this feature. If you have something like a cross zoom interaction in your chart, only the surface used to render the zoom rectangle repaints as you make a selection by dragging over the chart, while the series and axes surfaces are not repainted.

We can also rewrite the example above in an imperative way to better understand what’s going on:

var drawContainer = new Ext.draw.Container({
    renderTo: document.body,
    width: 250,
    height: 250
});

var mainSurface = drawContainer.getSurface(); // --- getSurface('main')

mainSurface.add({ // add sprite to the surface
    type: 'rect',
    x: 50,
    y: 50,
    width: 100,
    height: 100,
    lineWidth: 4,
    strokeStyle: 'green',
    fillStyle: 'yellow'
});

mainSurface.renderFrame(); // --- renders all the sprites in the surface

Open in a Fiddle

Modifying Sprite Attributes

Now, let’s have a look at how we can modify a sprite’s attributes. For example, we can make our rect sprite more rectangular than it is now by making it wider.

First, we need to get a reference to our sprite, and one way to do this would be to get the items config of the surface, which is an array of all the sprites that belong to the surface:

var items = mainSurface.getItems(),
    rectSprite = items[0];

Alternatively, we can use the surface’s get method:

var rectSprite = mainSurface.get(0);

Or, better yet, we can assign an ID to our sprite and use that to fetch it:

mainSurface.add({
    type: 'rect',
    id: 'myRect',
    ...
});

var rectSprite = mainSurface.get('myRect');

Now we can change the sprite’s width. This is how we do it:

rectSprite.setAttributes({
    width: 150
});
// --- Don't forget to repaint the surface after changing sprite's attributes
mainSurface.renderFrame();

You’ll notice that we can’t use rectSprite.setWidth(150); because width is not a config.

Sprite

Open in a Fiddle

We can also set more than one attribute at once, which is the recommended and more efficient way to do it. Let’s now change the colors of both fill and the stroke:

rectSprite.setAttributes({
    fillStyle: 'rgba(255, 0, 0, .5)',
    strokeStyle: 'rgb(0, 0, 0)'
});

Here, instead of using named colors, we use CSS compliant rgb functions to specify our color values.

Sprite

Open in a Fiddle

Try changing other attributes too and see how it affects the sprite. You can refer to the Ext JS docs to see which attributes are supported.

Conclusion

As you can see, using sprites is not much different than using components. The same principles of components are used with sprites. Instead of dealing with HTML directly, the component-like approach saves you time by not having to directly deal with SVG elements and Canvas API calls. You simply create sprites and configure the attributes, and the Draw package takes care of the rest.

In the next part of this series, you’ll learn how to animate, transform and interact with sprites, including the methods and approaches to create your own sprites. We will also cover special sprites features such as instancing and composites, which will help you to improve performance and reduce the complexity of your code.

Sprite

In the meantime, we hope you have fun trying out different types of sprites such as circle, line, or text which are available in the drawing package.

Recommended Articles

Guide to Estimating ROI When Switching From DIY Libraries to Full Software Development Platforms Like Ext JS

Teams started with Do It Yourself, or DIY, JavaScript tools like jQuery and Bootstrap. But those fall apart as projects scale. Scattered code, user interface…

Top Frameworks Developers Are Using for Custom Software Development in 2025

We’re seeing it more every year; teams aren’t settling for plug-and-play tools anymore. In healthcare, finance, logistics, and other data-heavy industries, there’s a clear shift.…

Meet Sencha AI Coding Companion: Your AI-Powered Assistant for Faster Ext JS Development

Building modern web applications should be exciting. But too often, developers find themselves buried in documentation, endlessly Googling framework quirks, or stuck solving the same…

Ext JS 7.9 & Rapid Ext JS V1.1 Have Arrived

The Sencha team is excited to announce the latest Ext JS version 7.9 and Rapid Ext JS 1.1 release – designed to accelerate development, enhance…

Top 10 JS Grid Customization Tips for a Better UI Experience

Grids are pretty much everywhere in web apps. Working with financial sheets, product details, or users? Then you’ve probably used a JavaScript grid. It makes…

Why Ext JS Framework is the Go-To Framework for Building Scalable and Data-Intensive Web Apps

Web apps are much more advanced now. They deal with large amounts of data and need to stay fast, even with many users. If you’re…

View More

Trusted by Top Developers: Learn how to enhance your development journey — for free

Get the latest newsletter keeping thousands of developers in the loop.

Loved by developers at