如何使用javascript对象在d3 v4中绘制一条线?

时间:2017-09-19 10:52:40

标签: javascript d3.js

我有以下对象

<?php

namespace AppBundle\Admin;

use AppBundle\Entity\Customer;
use AppBundle\Entity\Job;
use AppBundle\Form\Types;
use AppBundle\Repository\CustomerRepository;
use AppBundle\Service\EntityManager;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
use Sonata\AdminBundle\Show\ShowMapper;

class JobAdmin extends BaseAdmin
{
    const CONTACT_PERSON_DROPDOWN_PREFIX = 'contactPersons';

    /**
     * @param Job $job
     * @return null|string
     */
    protected function getPreselectedCustomerId(Job $job)
    {
        if ($job) {
            $customer = $job->getCustomer();

            if ($customer) {
                $customerId = $customer->getId();

                return $customerId;
            }
        }

        return null;
    }

    /**
     * @return \Doctrine\ORM\EntityRepository
     */
    protected function getEnabledCustomers()
    {
        $customerRepository = $this->getCustomerRepository();
        $customers          = $customerRepository->findByEnabled();

        return $customers;
    }

    /**
     * @param $enabledCustomers
     * @return array
     */
    protected function getFilterMap($enabledCustomers)
    {
        $filterMap = [];

        /**
         * @var $customer Customer
         */
        foreach ($enabledCustomers as $customer) {
            $customerId             = $customer->getId();
            $fieldName              = self::CONTACT_PERSON_DROPDOWN_PREFIX . $customerId;
            $filterMap[$customerId] = [$fieldName];
        }

        return $filterMap;
    }

    /**
     * @param $enabledCustomers
     * @return array
     */
    protected function getCustomerDropDown($enabledCustomers)
    {
        $customerDropDown = [];

        /**
         * @var $customer Customer
         */
        foreach ($enabledCustomers as $customer) {
            $customerId              = $customer->getId();
            $name                    = $customer->getName();
            $customerDropDown[$name] = $customerId;
        }

        return $customerDropDown;
    }

    /**
     * @param Customer $customer
     * @return \Doctrine\ORM\QueryBuilder
     */
    protected function getFilterQueryForCustomer(Customer $customer)
    {
        $entityManager      = $this->getEntityManager();
        $contactPersonQuery = $entityManager->createQueryBuilder('cp')
            ->select('cp')
            ->from('AppBundle:ContactPerson', 'cp')
            ->where('cp.customer = :customer')
            ->setParameter('customer', $customer)
            ->orderBy('cp.name', 'ASC')
        ;

        return $contactPersonQuery;
    }

    /**
     * @param FormMapper $formMapper
     */
    protected function configureFormFields(FormMapper $formMapper)
    {
        $job              = $this->getSubject();
        $enabledCustomers = $this->getEnabledCustomers();
        $filterMap        = $this->getFilterMap($enabledCustomers);
        $customerDropDown = $this->getCustomerDropDown($enabledCustomers);
        $preselectedId    = $this->getPreselectedCustomerId($job);

        $formMapper
            ->tab('BaseData')
                ->with('JobData')
                    ->add('customer', 'sonata_type_choice_field_mask', array(
                        'choices'      => $customerDropDown,
                        'data'         => $preselectedId,
                        'map'          => $filterMap,
                        'by_reference' => false,
                        'required'     => true,
                        'mapped'       => false,
                        )
                    )
                ->end()
            ->end()
        ;

        /**
         * @var $customer Customer
         */
        foreach ($enabledCustomers as $customer) {
            $customerId  = $customer->getId();
            $fieldName   = self::CONTACT_PERSON_DROPDOWN_PREFIX . $customerId;
            $filterQuery = $this->getFilterQueryForCustomer($customer);

            $formMapper
                ->tab('BaseData')
                    ->with('JobData')
                        ->add($fieldName, 'sonata_type_model', array(
                            'class'  => 'AppBundle\Entity\ContactPerson',
                            'query'  => $filterQuery,
                            'mapped' => false,
                            'label'  => 'Contact Person'
                        ))
                    ->end()
                ->end()
            ;
        }

        $formMapper
            ->tab('BaseData')
                ->with('JobData')
                    ->add('name')
                    // Add more fields
                ->end()
            ->end()
        ;
    }

    /**
     * @param EntityManager $entityManager
     * @return \Doctrine\ORM\EntityRepository
     */
    protected function getCustomerRepository(EntityManager $entityManager = null)
    {
        if (!$entityManager) {
            $entityManager = $this->getEntityManager();
        }

        $customerRepository = $entityManager->getRepository(Customer::class);

        return $customerRepository;
    }

    /**
     * @return EntityManager
     */
    protected function getEntityManager()
    {
        $entityManager = $this->getConfigurationPool()->getContainer()->get('doctrine')->getManager();

        return $entityManager;
    }

    /**
     * @param Job $job
     */
    protected function mapUnmappedFields (Job $job)
    {
        $customerId = $this->getForm()->get('customer')->getData();

        if ($customerId)
        {
            $entityManager      = $this->getEntityManager();
            $contactPerson      = $this->getForm()->get(self::CONTACT_PERSON_DROPDOWN_PREFIX.$customerId)->getData();
            $customerRepository = $this->getCustomerRepository($entityManager);
            $customer           = $customerRepository->findById($customerId);

            if ($contactPerson) {
                $job->setContactPerson($contactPerson);
            }

            if ($customer) {
                $job->setCustomer($customer);
            }

            $entityManager->persist($job);
            $entityManager->flush($job);
        }
    }

    /**
     * @param mixed $object
     */
    public function postPersist($object)
    {
        $this->mapUnmappedFields($object);

        parent::postPersist($object);
    }

    /**
     * @param mixed $object
     */
    public function postUpdate($object)
    {
        $this->mapUnmappedFields($object);

        parent::postUpdate($object);
    }
}

我想在d3 v4中的var data =[ {"steps":200,calories:200,distance:200,date:new Date(2012,09,1)}, {"steps":200,calories:200,distance:200,date:new Date(2012,09,2)}, {"steps":200,calories:200,distance:200,date:new Date(2012,09,3)}, {"steps":200,calories:200,distance:200,date:new Date(2012,09,4)}, {"steps":200,calories:200,distance:200,date:new Date(2012,09,5)}, ] steps对象之间绘制图表

我正在做这样的事情来画一条线。这是完整的代码..

date

我检查了检查器,x()和y()函数似乎返回了要在图形上绘制的右像素。

但是在检查器中该行的路径是 var dataLine = [ {"x":new Date(2012,0,1),"y":10}, {"x":new Date(2012,0,2),"y":9}, {"x":new Date(2012,0,3),"y":3}, {"x":new Date(2012,0,4),"y":2} ]; var parseTime = d3.timeParse("%d-%b-%y"); var svgContainer = d3.select(".dsh-svg-element"); var MARGIN = {left:50,right:20,top:20,bottom:30}; var WIDTH = 960 - (MARGIN.left + MARGIN.right); var HEIGHT = 500 - (MARGIN.top + MARGIN.bottom); svgContainer.attr("width",WIDTH+(MARGIN.left + MARGIN.right)) .attr("height",HEIGHT+(MARGIN.top+MARGIN.bottom)) .attr("transform","translate(" + MARGIN.left + "," + MARGIN.top + ")"); var xMax =100; var yMax =100; var x = d3.scaleTime().domain([new Date(2012,0,1), new Date(2012,0,31)]).range([0, WIDTH]) var y = d3.scaleLinear().domain([0,yMax]).range([HEIGHT,0]); var xAxis = d3.axisBottom(x); var yAxis = d3.axisLeft(y); svgContainer.append("g").attr("transform", "translate(50," + (HEIGHT+MARGIN.top) + ")").call(xAxis) svgContainer.append("g").attr("transform", "translate(50,20)").call(yAxis).attr("id","yAxis") var lineFunction = d3.line().x(function(d){return x(d.y)}).y(function(d){return y(d.x)}) svgContainer.append("path") .attr("d",lineFunction(dataLine)) .attr("stroke","blue").attr("stroke-width", 2).attr("fill", "none"); 。它似乎是在svg元素之外绘制线。知道如何解决这个问题吗?

有关绘制线条的任何提示或简单代码均表示赞赏。

Fiddle

1 个答案:

答案 0 :(得分:1)

您有两个主要问题:

首先,您的x域与您的数据阵列完全无关。只需使用d3.extent获取第一个和最后一个日期:

var x = d3.scaleTime()
    .domain(d3.extent(dataLine, function(d) {
        return d.x
    }))
    .range([MARGIN.left, WIDTH])

其次,您的线路生成器错误,您使用的d.x具有y比例,d.y使用x比例。它应该是:

var lineFunction = d3.line()
    .x(function(d) {
        return x(d.x)
    }).y(function(d) {
        return y(d.y)
    })

这是您更新的小提琴:https://jsfiddle.net/mxsLdntg/

请注意,小提琴中的线条基于dataLine,而不是data。您必须决定要使用哪个数据阵列并相应地设置域。