2017-09-11 30 views
-2

私はd3.jsコンポーネントtimeknotsを使用します。このコンポーネントは、linecircle要素で構成されています。このコンポーネントを少し修正しました。 divもラベルのラッパーとして使用されています。ユーザーが円の要素の上を移動すると、ラベル付きのdiv要素が表示されます。d3.js mouseoutが自動的に起動されます

ユーザーが円の上に移動すると、mouseoverがトリガーされます。円の場合はmouseoutハンドラー、ラベルの場合はmouseenterが自動的にトリガーされますが、理由はわかりません。

jsfiddle

HTML

<div id="timeline1" style="width:500px;"></div> 

ジャバスクリプト

var TimeKnots = { 
    draw: function(id, events, options){ 
    var cfg = { 
     width: 600, 
     height: 200, 
     radius: 10, 
     lineWidth: 4, 
     color: "#999", 
     background: "#FFF", 
     dateFormat: "%Y/%m/%d %H:%M:%S", 
     horizontalLayout: true, 
     showLabels: false, 
     labelFormat: "%H:%M:%S", 
     addNow: false, 
     seriesColor: d3.scale.category20(), 
     dateDimension: true, 
     initTime: "0", 
     duration: "0" 
    }; 

    //default configuration overrid 
    if(options != undefined){ 
     for(var i in options){ 
     cfg[i] = options[i]; 
     } 
    } 
    if(cfg.addNow != false){ 
     events.push({date: new Date(), name: cfg.addNowLabel || "Today"}); 
    } 

    // sort events according to dates 
    events.sort(function(a,b){ 
     // Turn your strings into dates, and then subtract them 
     // to get a value that is either negative, positive, or zero. 
     if (cfg.dateFormat.indexOf("%Y") === -1){ 
      return new Date("1971-01-01T" + a.date) - new Date("1971-01-01T" + b.date); 
     } 
     return new Date(a.date) - new Date(b.date); 
     }); 

    var idIndex = ""; 

    var svg = d3.select(id).append('svg').attr("class", "timeline") 
    .attr("width", cfg.width).attr("height", cfg.height).on("mouseover", function(d){ 
     if ($("#poi-"+idIndex).length > 0){ 
     console.log(idIndex + "hover", $("#poi-"+idIndex).is(":hover")); 
     } 

    }); 
    svg.append('defs') 
    .append("linearGradient") 
    .attr("id", "gradient").attr("gradientUnits", "userSpaceOnUse") 
    .attr("y1", "0px").attr("y2", "0px") 
    .attr("x1", "0px").attr("x2", "0px"); 
    svg.select('linearGradient').append("stop").attr("stop-color", "#1689fb"); 
    svg.select('linearGradient').append("stop").attr("stop-color", "rgb(126, 126, 126)"); 

    var tip = d3.select(id) 
    .append('div') 
    .attr("class","label-wrapper") 
    .style("position", "absolute") 
    .style("font-weight", "300") 
    .style("color", "white"); 

    svg.append('g') 
    .attr("stroke", "url(#gradient)") 
    .attr("class", "wrapper-timeline"); 
    //Calculate times in terms of timestamps 
    if(!cfg.dateDimension){ 
     var timestamps = events.map(function(d){ 
     if (cfg.dateFormat.indexOf("%Y") !== -1){ 
      return Date.parse(d.date); 
     } 
     return Date.parse("1971-01-01T" + d.date); 
     });//new Date(d.date).getTime()}); 
     var maxValue = d3.max(timestamps); 
     var minValue = d3.min(timestamps); 
    }else{ 
     var timestamps = events.map(function(d){ 
     if (cfg.dateFormat.indexOf("%Y") !== -1){ 
      return Date.parse(d.date); 
     } 
     return Date.parse("1971-01-01T" + d.date); 
     });//new Date(d.date).getTime()}); 
     var maxValue = d3.max(timestamps); 
     var minValue = d3.min(timestamps); 
    } 
    var margin = (d3.max(events.map(function(d){return d.radius})) || cfg.radius)*1.5+cfg.lineWidth; 
    var step = (cfg.horizontalLayout)?((cfg.width-2*margin)/(maxValue - minValue)):((cfg.height-2*margin)/(maxValue - minValue)); 
    var series = []; 
    if(maxValue == minValue){step = 0;if(cfg.horizontalLayout){margin=cfg.width/2}else{margin=cfg.height/2}} 

    linePrevious = { 
     x1 : null, 
     x2 : null, 
     y1 : null, 
     y2 : null 
    } 

    var minX = 0; 
    var maxX = 0; 
    var yPos = 0; 
    var cxPoints = new Array(); 

    d3.select(id + " svg g") 
    .append('g') 
    .attr("clip-path", "url(#clipLine)") 
    .attr("class", "wrapper-lines"); 

    svg.select('.wrapper-lines').selectAll("line") 
    .data(events).enter().append("line") 
    .attr("class", "timeline-line") 
     .attr("x1", function(d, i){ 
         var ret; 
         if(cfg.horizontalLayout){ 

         var timeInMil = new Date(); 

         if (cfg.dateFormat.indexOf("%Y") !== -1){ 
          timeInMil = new Date(d.date).getTime(); 
         } else { 
          timeInMil = new Date("1971-01-01T" + d.date).getTime(); 
         } 

         var datum = (cfg.dateDimension) ? timeInMil : d.value; 
         ret = Math.floor(step*(datum - minValue) + margin) 
         } 
         else{ 
         ret = Math.floor(cfg.width/2) 
         } 
         linePrevious.x1 = ret 
         if (i == 0){ 
         minX= ret; 
         } 
         return ret; 
         }) 
    .attr("x2", function(d, i){ 
         if (linePrevious.x1 != null){ 
          if (i == 0){ 
          maxX = linePrevious.x1; 
          } 
          return linePrevious.x1 
         } 
         if(cfg.horizontalLayout){ 
         var timeInMil = new Date(); 

         if (cfg.dateFormat.indexOf("%Y") !== -1){ 
          timeInMil = new Date(d.date).getTime(); 
         } else { 
          timeInMil = new Date("1971-01-01T" + d.date).getTime(); 
         } 

         var datum = (cfg.dateDimension) ? timeInMil : d.value; 
         ret = Math.floor(step*(datum - minValue)) 
         } 
         return Math.floor(cfg.width/2); 
         }) 
    .attr("y1", function(d, i){ 
         var ret; 
         if(cfg.horizontalLayout){ 
         ret = Math.floor(cfg.height/2) 
         } 
         else{ 
         var timeInMil = new Date(); 

         if (cfg.dateFormat.indexOf("%Y") !== -1){ 
          timeInMil = new Date(d.date).getTime(); 
         } else { 
          timeInMil = new Date("1971-01-01T" + d.date).getTime(); 
         } 

         var datum = (cfg.dateDimension) ? timeInMil : d.value; 
         ret = Math.floor(step*(datum - minValue)) + margin 
         } 
         linePrevious.y1 = ret 
         if (i === 0){ 
         yPos = ret; 
         } 
         return ret 
         }) 
    .attr("y2", function(d){ 
         if (linePrevious.y1 != null){ 
         return linePrevious.y1 
         } 
         if(cfg.horizontalLayout){ 
         return Math.floor(cfg.height/2) 
         } 
         var timeInMil = new Date(); 

         if (cfg.dateFormat.indexOf("%Y") !== -1){ 
         timeInMil = new Date(d.date).getTime(); 
         } else { 
         timeInMil = new Date("1971-01-01T" + d.date).getTime(); 
         } 

         var datum = (cfg.dateDimension) ? timeInMil : d.value; 
         return Math.floor(step*(datum - minValue)) 
         }) 

    .style("stroke-width", cfg.lineWidth); 

    var lastClipPathVal = ""; 

    var idIndexInOut = ""; 

    var timeout; 
    var mouseOutTimer; 

    svg.select(".wrapper-timeline").selectAll("circle") 
    .data(events).enter() 
    .append("circle") 
    .attr("class", function (d, i) { 
     return "timeline-event"; 
    }) 
    .attr("id", function (d, i) { 
     return "knot-" + i; 
    }) 
    .attr("r", function(d){if(d.radius != undefined){return d.radius} return cfg.radius}) 

    .style("stroke-width", function(d){if(d.lineWidth != undefined){return d.lineWidth} return cfg.lineWidth}) 
    .style("fill", "rgba(220,220,220, 0.01)") 
    .attr("cy", function(d){ 
     if(cfg.horizontalLayout){ 
      return Math.floor(cfg.height/2) 
     } 
     var timeInMil = new Date(); 

     if (cfg.dateFormat.indexOf("%Y") !== -1){ 
      timeInMil = new Date(d.date).getTime(); 
     } else { 
      timeInMil = new Date("1971-01-01T" + d.date).getTime(); 
     } 

     var datum = (cfg.dateDimension) ? timeInMil : d.value; 
     return Math.floor(step*(datum - minValue) + margin) 
    }) 
    .attr("cx", function(d, i){ 

     var radius = this.getAttribute("r") != undefined ? this.getAttribute("r") : cfg.radius; 

     var x = 0; 

     if(cfg.horizontalLayout){ 
      var timeInMil = new Date(); 

      if (cfg.dateFormat.indexOf("%Y") !== -1){ 
      timeInMil = new Date(d.date).getTime(); 
      } else { 
      timeInMil = new Date("1971-01-01T" + d.date).getTime(); 
      } 

      var datum = (cfg.dateDimension) ? timeInMil : d.value; 
      x = Math.floor(step*(datum - minValue) + margin); 
      cxPoints.push(x); 
      return x; 
     } 
     x = Math.floor(cfg.width/2); 
     cxPoints.push(x); 
     return x; 
    }).on("mouseover", function(d){ 

     if(cfg.dateDimension){ 
     var format = d3.time.format(cfg.dateFormat); 
     var datetime = format(new Date(d.date)); 
     var dateValue = (datetime != "")?(d.name +" <small>("+datetime+")</small>"):d.name; 
     }else{ 
     var format = function(d){return d}; // TODO fix date formatting 
     var datetime = d.value; 
     var dateValue = d.name +" <small>("+d.value+")</small>"; 
     } 

     idIndex = d3.select(this).attr("id").replace('knot-',''); 

     timeout = setTimeout(function(){ 
     $("#poi-"+idIndex).css({display: "flex"}) 
          .hide() 
          .fadeIn() 
          .addClass("hovered"); 
     }, 400); 

     lastClipPathVal = $(this).attr("clip-path"); 
     $(this).removeAttr("clip-path"); 

     d3.select(this) 
     .style("fill", "white").transition() 
     .duration(100).attr("r", function(d){if(d.radius != undefined){return Math.floor(d.radius*1.8)} return Math.floor(cfg.radius*1.8)}) 

    }) 
    .on("mouseout", function(){ 

     idIndexInOut = d3.select(this).attr("id").replace('knot-',''); 
     clearTimeout(timeout); 

     console.log("mouseout " + idIndexInOut); 

     mouseOutTimer = setTimeout(function(){ 
      console.log("fadeoutTriggered " + idIndexInOut); 
      $("#poi-"+idIndexInOut).fadeOut("fast"); 
     }, 400); 

     d3.select(this) 
     .style("fill", "rgba(220,220,220, 0.01)").transition() 
     .duration(100).attr("r", function(d){if(d.radius != undefined){return d.radius} return cfg.radius}) 
     .attr("clip-path", lastClipPathVal);; 

    }); 

    // svg.append("use").attr("xlink:href", ''); 

    var labelWrapper = d3.select('.label-wrapper') 
    .style("width", cfg.width + "px") 
    .style("left", "112px"); 
    var topOffset = -50; 
    console.log(topOffset) 
    var leftToRight = true; 

    // Append POI's 
    for (var idx = 0; idx < events.length; idx++) { 

     if (cxPoints[idx] <= d3.select(id).node().getBoundingClientRect().width/2){ 
     leftToRight = true; 
     } else { 
     leftToRight = false; 
     } 

     var poiWrapper = labelWrapper.append('div') 
     .attr("id", "poi-" + idx) 
     .attr("class",function() { 

     var className = "poi-wrapper"; 

     if (events[idx].type && events[idx].type === 'link'){ 
      return className += " poi-link"; 
     } else { 
      return className; 
     } 
     }); 

     var poiImg = ''; 

     if (events[idx].type && events[idx].type === 'link'){ 
     poiImg = poiWrapper.append("div").attr("class", "background-img"); 

     var linkContent = poiWrapper.append("div").attr("class", "link-content") 
     linkContent.append("span").attr("class", "poi-header").html(events[idx].heading); 
     linkContent.append("span").attr("class", "poi-subheading").html(events[idx].subHeading); 
     linkContent.append("ul") 
     .attr("class", "poi-details") 
     .append("li").html("<i class=\"fa fa-comment\" aria-hidden=\"true\"></i> " + events[idx].details); 
     } 

     if (events[idx].type !== 'topic'){ 
     if (leftToRight){ 
      if (poiImg.length > 0){ 
      poiWrapper.style("height", "100px"); 
      var ImgSvg = poiImg.append("svg").attr("class", "poi-image"); 

      ImgSvg.attr("class", "svg-defs").attr("width", "110px") 
      .append('defs').append("clipPath").attr("id", "clip-triangle-"+[idx]) 
      .append("polygon").attr("points", "0,0 110,0 110,100 19,100 12,107 5,100 0,100 0,0"); 

      ImgSvg.append("rect").attr("class","svg-background").attr("clip-path", "url(#clip-triangle-"+[idx]+ ")").attr("width", "110px").attr("height", "110px"); 
      ImgSvg.append("image").attr("class","svg-image").attr("clip-path", "url(#clip-triangle-"+[idx]+ ")").attr("width", "110px").attr("height", "110px") 
      .attr("xlink:href", events[idx].img); 

      poiImg.style({'width': '110px','height': '110px'}); 
      } 
     } else { 
      poiWrapper.append("div").attr("class", "arrow-down-empty-anchor"); 
      if (poiImg.length > 0){ 
      poiWrapper.style("height", "100px"); 

      poiImg.style({'background': "url(" + events[idx].img + ")", 
      'background-size': "100px 100px", 
      'background-repeat': "no-repeat", 
      'width': '100px', 
      'height': '100px'}); 
      } 
     } 
     } 

     $("#poi-" + idx).on(
     { 
      mouseenter: function() 
      { 
      console.log("hover poi - clear timeout"); 
      // poiHovered = true; 
      clearTimeout(mouseOutTimer); 
      }, 
      mouseleave: function() 
      { 
      console.log("unhover poi"); 
      // poiHovered = false; 
      mouseOutTimer = setTimeout(function(){ 
       console.log("fadeoutTriggered"); 
       $("#poi-"+idIndex).fadeOut("fast"); 
       // $("#poi-"+idIndex).css("zIndex", 0); 
      }, 400); 
      } 
     }); 

     poiWrapper.style("position", "absolute") 
     .style("color", "black") 
     .style("top", function(d) { 
     return topOffset - this.clientHeight - 30 + "px"; 
     }) 

     if (leftToRight){ 
     if (events[idx].type === 'topic'){ 

      poiWrapper.style("left", (cxPoints[idx]) +"px"); 
     } else { 
      console.log(cxPoints[idx]); 
      poiWrapper.style("left", (cxPoints[idx]- 120) +"px"); 
     } 
     } else { 
     var mainLineWidth = d3.select(".wrapper-timeline line").node().getBoundingClientRect().width; 
     var vertOffset = mainLineWidth - cxPoints[idx]; 
     poiWrapper.style("right", vertOffset + "px") 
     } 

     poiWrapper.style("display", "none"); 
    } 

    //Adding start and end labels 
    if(cfg.showLabels != false){ 
     var measuredTime = new Date(null); 

     if(cfg.duration){ 
     measuredTime.setSeconds(cfg.duration); 
     var endString = measuredTime.toISOString().substr(12, 7); 
     } else { 
     var endString = duration; 
     } 

     svg.append("text") 
     .text(endString).style({"font-size": "70%", "font-weight": "bold", "fill": "#7e7e7e"}) 
     .attr('class', 'duration') 
     .attr("x", function(d){if(cfg.horizontalLayout){return cfg.width - d3.max([this.getBBox().width, (margin+this.getBBox().width/2)])} return Math.floor(this.getBBox().width/2)}) 
     .attr("y", function(d){if(cfg.horizontalLayout){return Math.floor(cfg.height/2+(margin+this.getBBox().height))}return cfg.height-margin+this.getBBox().height/2}) 
    } 
    } 
} 



var kurbickFilms = [ 
    { 
    type: "link", 
    date: "00:00:00", 
    img: 
     "http://upload.wikimedia.org/wikipedia/en/thumb/6/6c/Seafarers_title.jpg/225px-Seafarers_title.jpg", 
    heading: "Revenerace for Putin on the right buys trump cover", 
    subHeading: "NYTIMES/JEREMY PETERS", 
    details: "3" 
    }, 
    { 
    type: "link", 
    date: "00:10:25", 
    img: 
     "http://upload.wikimedia.org/wikipedia/en/thumb/6/6c/Seafarers_title.jpg/225px-Seafarers_title.jpg", 
    heading: "Revenerace for Putin on the right buys trump cover", 
    subHeading: "NYTIMES/JEREMY PETERS", 
    details: "3" 
    }, 
    { 
    type: "link", 
    date: "00:10:25", 
    img: 
     "http://upload.wikimedia.org/wikipedia/en/thumb/6/6c/Seafarers_title.jpg/225px-Seafarers_title.jpg", 
    heading: "Revenerace for Putin on the right buys trump cover", 
    subHeading: "NYTIMES/JEREMY PETERS", 
    details: "3" 
    }, 
    { 
    type: "link", 
    date: "01:11:24", 
    img: 
     "http://upload.wikimedia.org/wikipedia/en/thumb/6/6c/Seafarers_title.jpg/225px-Seafarers_title.jpg", 
    heading: "Revenerace for Putin on the right buys trump cover", 
    subHeading: "NYTIMES/JEREMY PETERS", 
    details: "3" 
    } 
]; 

TimeKnots.draw("#timeline1", kurbickFilms, { 
    showLabels: true, 
    dateFormat: "%H:%M:%S", 
    color: "#7e7e7e", 
    width: 800, 
    height: 100, 
    labelFormat: "%H:%M:%S", 
    lineWidth: 2, 
    radius: 6, 
    duration: "4284.839125" 
}); 

CSS

svg.poi-image { 
    position: absolute; 
    height: 110px; 
    width: 110px; 
} 

.poi-wrapper{ 
    display: flex; 
    background: #61b4f7; 
    z-index: 2; 
} 

.poi-intro, .poi-twitter, .poi-link, .poi-interview, .poi-add, .poi-comment{ 
    width: 300px; 
} 

答えて

0

svg要素があり、それはcircle要素をオーバーレイします。

+0

」が見えないのはどこですか?例ではオーバーレイはありません。 – altocumulus

+0

@altocumulus元の質問のjsfiddleを確認してください。それは '.svg-defs'要素です。 – Matt

関連する問題