2

I am writing a drawing editor using jquery-ui where you can add/remove shapes and move and resize them. This all works fine. But if I add too many shapes, then resizing one shape gets really slow. I made a jsfiddle, where you can see it, but in my editor it's 10 times slower with less shapes. I think because I have other event handler in there.

Here is the fiddle where resizing is fast: http://jsfiddle.net/oh6e9k6k/

And here the slow one with many shapes (takes some time to load): http://jsfiddle.net/oh6e9k6k/1/

The effect can be see best in Internet explorer.

Is there a chance to improve the performance with such a big amount of shapes? As I said in my editor it's even much slower whith even less shapes.

I want to avoid to do such things like attach the handlers only if user clicks on that shape and remove it if resizing/dragging is finished, but if there is no other solution, then maybe I have to.

Here is how the shapes get their functionality:

$(".shape").resizable({
    start: function (event, ui) {
        $(this).addClass("highliteShape");
    },
    stop: function (event, ui) {
        $(this).removeClass("highliteShape");
    }
}).draggable({
    cursor: "move",
     start: function (event, ui) {
        $(this).addClass("highliteShape");
    },
    stop: function (event, ui) {
        $(this).removeClass("highliteShape");
    }
});

I made a screencast from the real application to show what I mean: http:// screencast.com/t/r3xCwWdbp

2 Answers2

1

I created a demo for you using an async function to demostrated were the problem lies. You can see drawing the boxes takes no time at all, but the function to enlarge each box is whats the problem. Anyway at least with this function you can actually see somethig instead of waiting.

Demo (click ok after finished alert and will notice the time it takes for the Enlarge function to complete)

http://jsfiddle.net/007k03jx/

$(document).ready(function() {

     /// the Assync function.

    var asyncFor = function(params) {

        var defaults = {
          total: 0,
          limit: 1,
          pause: 10,
          context: this
        },
          options = $.extend(defaults, params),
          def = $.Deferred(),
          step = 0,
          done = 0;

        this.loop = function() {
          if (done < options.total) {
            step = 0;
            for (; step < options.limit; step += 1, done += 1) {
              def.notifyWith(options.context, [done]);
            }
            setTimeout.apply(this, [this.loop, options.pause]);
          } else {
            def.resolveWith(options.context);
          }
        };

        setTimeout.apply(this, [this.loop, options.pause]);
        return def;
      };

var maxSize = 2000;
var x=0;

    asyncFor({
      total:50,      
      context: this
    }).progress(function(step) {

var y=0;
    for(var y=0; y<maxSize; y+=35){

 $("#ShapeContainer").append("<div class='shape' style='left:" + x + "px; top:" + y + "px;'><div>x</div></div>"); 



    }

x+=35;


     }).done(function() {

    alert("finished")
resize() 
    });

  function resize() {  
                   $(".shape").resizable({
        start: function (event, ui) {
            $(this).addClass("highliteShape");
        },
        stop: function (event, ui) {
            $(this).removeClass("highliteShape");
        }
    }).draggable({
        cursor: "move",
         start: function (event, ui) {
            $(this).addClass("highliteShape");
        },
        stop: function (event, ui) {
            $(this).removeClass("highliteShape");
        }
    });
  }
    });
Tasos
  • 5,321
  • 1
  • 15
  • 26
  • Thanks, for that demo, but the time for loading is not the problem, as I load also async in my real application. And there is a much higher delay if you start resizing. I will try to replicate the delay more clearly. So my problem is that if there are much shapes, then if I try to resize one shape it starts with a huge delay of 1 or 2 seconds. Depends also how fast your machine is. – Kiriakos Tzannis Oct 09 '14 at 14:31
  • I made a screencast from the real application to show what I mean: http://screencast.com/t/r3xCwWdbp – Kiriakos Tzannis Oct 09 '14 at 14:55
  • looks very slow. have you looked into canvas instead. http://stackoverflow.com/questions/19100009/dragging-and-resizing-an-image-on-html5-canvas --- demo -- http://jsfiddle.net/m1erickson/LAS8L/ – Tasos Oct 10 '14 at 23:50
1

I found a workaround for my problem. I only initialize the event handler (resize/move/click/doubleclick) for my shapes on a mouse enter event for the shape. This has also increases the load time dramatically. Now resizing a shape happens instantly.

http://jsfiddle.net/oh6e9k6k/3/

var maxSize = 2000;

function InitShapeEventHandler($shape){
    if(!$shape.hasClass("ui-resizable")){
         $shape.resizable({
            start: function (event, ui) {
                $(this).addClass("highliteShape");
            },
            stop: function (event, ui) {
                $(this).removeClass("highliteShape");
            }
        }).draggable({
            cursor: "move",
             start: function (event, ui) {
                $(this).addClass("highliteShape");
            },
            stop: function (event, ui) {
                $(this).removeClass("highliteShape");
            }
        });
    }
}


for(var x=0; x<maxSize; x+=35){
    for(var y=0; y<maxSize; y+=35){
        $("#ShapeContainer").append("<div class='shape' style='left:" + x + "px; top:" + y + "px;'></div>");        
    }
}




$(function() {
    // add some dummy code
    $(".shape").append("<div>x</div>");

    $(".shape").mouseenter(function(){
        InitShapeEventHandler($(this));
    });   
});