Solved

Lines between circles 2 - Derived question

Posted on 2014-10-05
15
140 Views
Last Modified: 2014-10-08
Hi folks I'm in need to add a few funcionalities in the code below and I'd be very grateful to anyone who could do it. The first thing I need is that when a circle from the second tier that appears is clicked I need for the clicked circle move to the position of the original circle, I also need for the other circles generated by the first circle to hide before the new ones from behind the newly clicked circle to appear.

Well any help would be much appreciated.

Here is the code:

<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<title>Rodrigo</title>
<style type="text/css">
#circle-container {
  position: relative;
  margin: 0 auto;
  width: 500px;
  height: 500px;
  border: 0px solid green;
}
.circle-wrapper {
  position: absolute;  
  width: 500px;
  height: 500px;
  top: 0;
  left: 0;
}
.circle-wrapper:nth-of-type(1) {
  z-index: 1000
}
.circle {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 40px;
  background: red;
  left: 230px;
  top: 230px;
}
.blue {
  background: blue;
}
.green {
  background: green;
}
.yellow {
  background: yellow;
}
.orange {
  background: orange;
}
.pink {
  background: pink;
}
.purple {
  background: purple;
}
</style>
</head>
<body>
<div id="circle-container">
  <div class="circle-wrapper">
      <div class="circle animate blue"></div>
      <div class="circle animate green"></div>
      <div class="circle animate yellow"></div>
      <div class="circle animate orange"></div>
      <div class="circle animate pink"></div>
      <div class="circle animate purple"></div>
      <div id="circle" class="circle"></div>
  </div>
  <svg id="lines" height="500" width="500"></svg>  
</div>

<script src="jquery.js"></script>

<script>
 var clicked = false;
  var distanceToMove = 100;
  var clickedCircles = [];
  var total_circles = $('#circle-container .circle.animate').length;
  var angle = (Math.PI * 2 / total_circles);
  $('#circle').click(function() {
    if (clicked) return;
    clicked = true;
  var circlePos = $('#circle').position();
  var circlePosTop = circlePos.top + ($('#circle').outerWidth() / 2);
  var circlePosLeft = circlePos.left + ($('#circle').outerHeight() / 2);
    $('#circle-container .circle.animate').each(function(indx, item) {
      var top = distanceToMove * Math.cos(angle*(indx-1));
      var left = distanceToMove * Math.sin(angle *(indx-1));
      $(this).animate({left: "+=" + left, top: "+=" + top}, 1000, function(){;
      var newLine = document.createElementNS('http://www.w3.org/2000/svg','line');
      newLine.setAttribute('x1',circlePosLeft);
      newLine.setAttribute('y1',circlePosTop);
      newLine.setAttribute('x2',Math.floor(circlePosLeft + left));
      newLine.setAttribute('y2',Math.floor(circlePosTop + top));
      newLine.setAttribute('style','stroke:rgb(255,0,0);stroke-width:1');
      $('#lines').append(newLine);
    });
    });
  });
   $('#circle-container .circle.animate').click(function() {
    var thisIndex = $(this).index();
    var thisPos = $(this).position();
    var thisPosTop = thisPos.top + ($(this).outerWidth() / 2);
    var thisPosLeft = thisPos.left + ($(this).outerHeight() / 2);
    if($.inArray(thisIndex, clickedCircles) == -1){
      var circlesClone = $('.circle-wrapper:first').clone();
      $('#circle-container').append('<div id="circle-container_' + thisIndex + '" class="circle-wrapper"></div>');
      $(circlesClone).find('div:last').removeAttr('id');
      $(circlesClone).find('svg').removeAttr('id');
      $(circlesClone).find('div').each(function(indx, item) {
        $(this).css({top: thisPos.top, left: thisPos.left});
        var top = distanceToMove * Math.cos(angle*(indx-1));
        var left = distanceToMove * Math.sin(angle *(indx-1));
        $(this).animate({left: "+=" + left, top: "+=" + top}, 1000, function(){
          var newLine = document.createElementNS('http://www.w3.org/2000/svg','line');
          newLine.setAttribute('x1',thisPosLeft);
          newLine.setAttribute('y1',thisPosTop);
          newLine.setAttribute('x2',Math.floor(thisPosLeft + left));
          newLine.setAttribute('y2',Math.floor(thisPosTop + top));
          newLine.setAttribute('style','stroke:rgb(255,0,0);stroke-width:1');
          newLine.setAttribute('class','group' + thisIndex);
          $('#lines').append(newLine);
        });
        $('#circle-container_' + thisIndex).append($(this));
      });
      clickedCircles.push(thisIndex);
    }else{
      var remove = clickedCircles.indexOf(thisIndex);console.log(remove);
      if (remove > -1) {
          clickedCircles.splice(remove, 1);
          }
      $('.group' + thisIndex).remove();
      $('#circle-container_' + thisIndex + ' div').each(function() {    
        $(this).animate({left: thisPos.left, top: thisPos.top}, 1000, function() {
            $('#circle-container_' + thisIndex).remove();
        });
      });     
    }
  });
</script>



</body></html>

Open in new window

0
Comment
Question by:Rodric MacOliver
  • 9
  • 6
15 Comments
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40363070
I need for the clicked circle move to the position of the original circle
Which is the original - the red circle that appears on page load or the circle that appears when you click one of the circles on the circumference of the first red circle?

The code currently expands out to 16 circles - I am getting the impression that you want to keep a circle in the centre and always expand from that.

Is it correct that you want the following
a) First circle (red) appears on page load
b) Click this - 6 circles appear around the first
c) Click one of the 6 and it moves to the centre (red) circle before showing its children

Is that correct?
0
 

Author Comment

by:Rodric MacOliver
ID: 40363136
julianH, yes it seems that what you mentioned is what I want.

The first is the one that is the first to be clicked, and than its children come out from behind it,
When one click on on of its children the others must close (behind the parent from which they appeared) and the parent should disappear;
Then the children that was clicked should move to the center where its parent was and just disappeared and make its own children appear from behind like his parent had before him.

Does that make sense?

Thanks
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40363380
What is the process for navigating back?

Will one of the child circles be a back link?
0
 

Author Comment

by:Rodric MacOliver
ID: 40364580
julianH, I hadn't thought about that... Maybe instead of the first circle to disappear it should go to the bottom of the screen faded, this way it could always be brought back by clicking on it...

The more important feature is to be abble to go from father to son, and than from son to grandson and so forth...
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40365617
Some questions

How many levels must this go down to
How are you loading the levels - are these preloaded or are they generated
0
 

Author Comment

by:Rodric MacOliver
ID: 40365644
julianH, they must be loaded with ajax and they are retrieved from a database in a query. I want to have a circlefor each record that the query will return. So the first circle (that is referent to a single query) qill return for example 4 records, so it should show 4 circles coming from him. When you click on the "son" another query is called in ajax and return the number of records and so on...
Theoretically it should be scalable.
Cheers
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40365706
Ok - that makes sense - was not clear from your code.

This should be relatively straight forward - the only missing piece is what to do with the clicked circle's parent.

Otherwise it is
on click
    get children (AJAX)
    parent retrieves non-clicked siblings - animates them behind itself and removes lines
    animate clicked circle to center
    animate children out - as we have at the moment - and draw lines

Is that in line with what you are wanting.
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:Rodric MacOliver
ID: 40366952
julianH, yep, it seem to be what I need...
:)
The parent can disappear, I'll figura a way go back without it...
Cheers
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40367839
Here is a rough samples sans lines - you can put those back in
<!doctype html>
<html>
<head>
<title>Test</title>
<style type="text/css">
#circle-container {
  position: relative;
  width: 500px;
  height: 500px;
  margin: 0 auto;
  border: 1px solid green;
}
.circle {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 40px;
  background: red;
  left: 230px;
  top: 230px;
  z-index: 1;
}
#circle {
  z-index: 2000;
}
.blue {
  background: blue;
}
.green {
  background: green;
}
.yellow {
  background: yellow;
}
.orange {
  background: orange;
}
.pink {
  background: pink;
}
.purple {
  background: purple;
}
</style>
</head>
<body>
<div id="circle-container">
  <div class="circle child blue" data-id="1"></div>
  <div class="circle child green" data-id="2"></div>
  <div class="circle child yellow" data-id="3"></div>
  <div class="circle child orange" data-id="4"></div>
  <div class="circle child pink" data-id="5"></div>
  <div class="circle child purple" data-id="6"></div>
  <div id="circle" class="circle"></div>
</div>
<script src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
var distanceToMove = 100;

function hideCircles(selected)
{
  $('#circle-container div.circle').each(function(indx, item) {
    if (indx != selected) { 
    $(item).fadeOut(1000, function() {$(this).remove();});
    }
  });
}

function expandCircles()
{
  if ($('#circle').hasClass('expanded')) return;
  $('#circle').addClass('expanded');
  var total_circles = $('#circle-container .circle.child').length;
  var angle = (Math.PI * 2 / total_circles)
  $('#circle-container div.child').each(function(indx, item) {
    var top = distanceToMove * Math.cos(angle*(indx-1));
    var left = distanceToMove * Math.sin(angle *(indx-1)); 
    $(this).animate({left: "+=" + left, top: "+=" + top}, 1000);
  });
}
$(function() {

  $('#circle-container').on('click','#circle', function() {
    expandCircles();
  });
  
  $('#circle-container').on('click','.child', function() {
    var current = $(this);
    var index = $(this).index();
    $.ajax({
      url: 'getsubmenu.php',
      data: {id: $(this).data('id')},
      type: 'POST',
      dataType: 'JSON',
      success: function(response) {
        hideCircles(index);
        current.removeClass('child').attr('id','circle').animate({left: '230px', top: '230px'}, 1000, function() {
          for(i=0; i<response.length;i++) {
            $('#circle-container').append(
              $('<div/>').addClass('circle child type' + i).data('id', response[i])
            );
          }
          expandCircles()
        });
      }
    });
  });
});
</script>
</body>
</html>

Open in new window

Working sample here http://www.marcorpsa.com/ee/t717.html
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40367845
Slight update to the code above - the above code goes screwy if you click on another circle while it is loading a new menu
Change the hideCircles function to
function hideCircles(selected)
{
  // ADD THE addClass function call
  $('#circle-container div.circle').addClass('closing').each(function(indx, item) {
    if (indx != selected) { 
      $(item).fadeOut(1000, function() {$(this).remove();});
    }
  });
}

Open in new window

And the onclick to
  $('#circle-container').on('click','.child', function() {
    // ADD THIS LINE
    if ($(this).hasClass('closing') || $(this).attr('id') == 'circle') return;
    var current = $(this);
    var index = $(this).index();
    ...

Open in new window

0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40367846
Another slight change - to make the move to center of the selected circle not rely on hard coded co-ordinates
  $('#circle-container').on('click','.child', function() {
	if ($(this).hasClass('closing') || $(this).attr('id') == 'circle') return;
    var current = $(this);
    var index = $(this).index();
    $.ajax({
      url: 'getsubmenu.php',
      data: {id: $(this).data('id')},
      type: 'POST',
      dataType: 'JSON',
      success: function(response) {
        hideCircles(index);

        // ADD THESE TWO LINES AND CHANGE THE ANIMATE LINE
        var left = $('#circle').css('left');
        var top = $('#circle').css('top');
        current.removeClass('child').attr('id','circle').animate({left: left, top: top}, 1000, function() {

          for(i=0; i<response.length;i++) {
            $('#circle-container').append(
              $('<div/>').addClass('circle child type' + i).data('id', response[i])
            );
          }
          expandCircles()
        });
      }
    });
  });

Open in new window

0
 

Author Comment

by:Rodric MacOliver
ID: 40367864
julianH, its not working doing the modifications mentioned above...

The code would be something like this:

<!doctype html>
<html>
<head>
<title>Test</title>
<style type="text/css">
#circle-container {
  position: relative;
  width: 500px;
  height: 500px;
  margin: 0 auto;
  border: 1px solid green;
}
.circle {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 40px;
  background: red;
  left: 230px;
  top: 230px;
  z-index: 1;
}
#circle {
  z-index: 2000;
}
.blue {
  background: blue;
}
.green {
  background: green;
}
.yellow {
  background: yellow;
}
.orange {
  background: orange;
}
.pink {
  background: pink;
}
.purple {
  background: purple;
}
</style>
</head>
<body>
<div id="circle-container">
  <div class="circle child blue" data-id="1"></div>
  <div class="circle child green" data-id="2"></div>
  <div class="circle child yellow" data-id="3"></div>
  <div class="circle child orange" data-id="4"></div>
  <div class="circle child pink" data-id="5"></div>
  <div class="circle child purple" data-id="6"></div>
  <div id="circle" class="circle"></div>
</div>
<script src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
var distanceToMove = 100;

function hideCircles(selected)
{
  // ADD THE addClass function call
  $('#circle-container div.circle').addClass('closing').each(function(indx, item) {
    if (indx != selected) { 
      $(item).fadeOut(1000, function() {$(this).remove();});
    }
  });
}
                                          

function expandCircles()
{
  if ($('#circle').hasClass('expanded')) return;
  $('#circle').addClass('expanded');
  var total_circles = $('#circle-container .circle.child').length;
  var angle = (Math.PI * 2 / total_circles)
  $('#circle-container div.child').each(function(indx, item) {
    var top = distanceToMove * Math.cos(angle*(indx-1));
    var left = distanceToMove * Math.sin(angle *(indx-1)); 
    $(this).animate({left: "+=" + left, top: "+=" + top}, 1000);
  });
}
$(function() {

  $('#circle-container').on('click','#circle', function() {
    expandCircles();
  });

    
  $('#circle-container').on('click','.child', function() {
    if ($(this).hasClass('closing') || $(this).attr('id') == 'circle') return;
    var current = $(this);
    var index = $(this).index();
    $.ajax({
      url: 'getsubmenu.php',
      data: {id: $(this).data('id')},
      type: 'POST',
      dataType: 'JSON',
      success: function(response) {
        hideCircles(index);
        current.removeClass('child').attr('id','circle').animate({left: '230px', top: '230px'}, 1000, function() {
          for(i=0; i<response.length;i++) {
            $('#circle-container').append(
              $('<div/>').addClass('circle child type' + i).data('id', response[i])
            );
          }
          expandCircles()
        });
      }
    });
  });
});
</script>
</body>
</html>

Open in new window



Doing all that you mentioned above, but it doesn't work...
Cheers
0
 
LVL 51

Accepted Solution

by:
Julian Hansen earned 500 total points
ID: 40367872
Did you have a look at the online sample - that has all the working code in it. Recommend you do a view source on that and see what is different.

http://www.marcorpsa.com/ee/t717.html

I suspect the problem is that in my code I call a php script getsubmenu.php that just returns a JSON array of numbers
<?php
$return = array(
	1,2,3,4,5,6);
die(json_encode($return));
?>

Open in new window

This represents the AJAX call to get the next menu. I don't know how your menu data works so you will have to modify this to your specific situation.
However, check the link above first and see if that functionality is what you were looking for - after that we can look at how to apply it specifically to your situation.
0
 

Author Closing Comment

by:Rodric MacOliver
ID: 40367881
Yep julianH, I think this will work fine. If I need any more help with it I'll post it here. Thanks a lot.
Cheers
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40367902
You are welcome - thanks for the points
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

What is a Lightbox? A Lightbox is the effect you see when you click, for example, an image and the screen fades out and up pops the same image but in its full size dimensions. There are lots of Lightbox effects for jQuery. Problem is they are a…
Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now